@polycode-projects/the-mechanical-code-talker 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/bin/tmct.mjs +4 -5
  2. package/corpus/LICENSES.json +19 -4
  3. package/corpus/README.md +48 -0
  4. package/corpus/generated/README.md +24 -9
  5. package/corpus/generated/ace-surface-variants.jsonl +4 -1
  6. package/corpus/generated/manifest.json +4 -4
  7. package/corpus/prose/manifest.json +512 -0
  8. package/corpus/prose/sqlite/LICENSE-NOTICE +53 -0
  9. package/corpus/prose/sqlite/arch.txt +213 -0
  10. package/corpus/prose/sqlite/atomiccommit.txt +1117 -0
  11. package/corpus/prose/sqlite/faq.txt +473 -0
  12. package/corpus/prose/sqlite/fileformat.txt +1589 -0
  13. package/corpus/prose/sqlite/lang_createtable.txt +1339 -0
  14. package/corpus/prose/sqlite/lang_insert.txt +580 -0
  15. package/corpus/prose/sqlite/lang_select.txt +3293 -0
  16. package/corpus/prose/sqlite/optoverview.txt +908 -0
  17. package/corpus/prose/sqlite/queryplanner.txt +447 -0
  18. package/corpus/prose/sqlite/transactional.txt +41 -0
  19. package/corpus/prose/sqlite/wal.txt +567 -0
  20. package/corpus/prose/sqlite/whentouse.txt +300 -0
  21. package/corpus/prose/wikipedia/Apple.txt +4 -0
  22. package/corpus/prose/wikipedia/Attempto_Controlled_English.txt +169 -0
  23. package/corpus/prose/wikipedia/Automated_planning_and_scheduling.txt +67 -0
  24. package/corpus/prose/wikipedia/Bee.txt +7 -0
  25. package/corpus/prose/wikipedia/Bird.txt +8 -0
  26. package/corpus/prose/wikipedia/Bone.txt +4 -0
  27. package/corpus/prose/wikipedia/Book.txt +7 -0
  28. package/corpus/prose/wikipedia/Bread.txt +6 -0
  29. package/corpus/prose/wikipedia/Butterfly.txt +6 -0
  30. package/corpus/prose/wikipedia/Car.txt +1 -0
  31. package/corpus/prose/wikipedia/Cat.txt +1 -0
  32. package/corpus/prose/wikipedia/Child.txt +3 -0
  33. package/corpus/prose/wikipedia/City.txt +2 -0
  34. package/corpus/prose/wikipedia/Clock.txt +2 -0
  35. package/corpus/prose/wikipedia/Cooking.txt +1 -0
  36. package/corpus/prose/wikipedia/Description_logic.txt +660 -0
  37. package/corpus/prose/wikipedia/Doctor.txt +6 -0
  38. package/corpus/prose/wikipedia/Dog.txt +4 -0
  39. package/corpus/prose/wikipedia/Eagle.txt +4 -0
  40. package/corpus/prose/wikipedia/Emotion.txt +9 -0
  41. package/corpus/prose/wikipedia/Eye.txt +5 -0
  42. package/corpus/prose/wikipedia/Family.txt +3 -0
  43. package/corpus/prose/wikipedia/Farm.txt +4 -0
  44. package/corpus/prose/wikipedia/Fear.txt +4 -0
  45. package/corpus/prose/wikipedia/First-order_logic.txt +1518 -0
  46. package/corpus/prose/wikipedia/Fish.txt +10 -0
  47. package/corpus/prose/wikipedia/Flower.txt +3 -0
  48. package/corpus/prose/wikipedia/Food.txt +10 -0
  49. package/corpus/prose/wikipedia/Grass.txt +9 -0
  50. package/corpus/prose/wikipedia/Hand.txt +2 -0
  51. package/corpus/prose/wikipedia/Happiness.txt +3 -0
  52. package/corpus/prose/wikipedia/Heart.txt +4 -0
  53. package/corpus/prose/wikipedia/Horse.txt +4 -0
  54. package/corpus/prose/wikipedia/House.txt +6 -0
  55. package/corpus/prose/wikipedia/Human.txt +4 -0
  56. package/corpus/prose/wikipedia/Insect.txt +6 -0
  57. package/corpus/prose/wikipedia/Interactive_fiction.txt +112 -0
  58. package/corpus/prose/wikipedia/Knowledge.txt +5 -0
  59. package/corpus/prose/wikipedia/Knowledge_representation_and_reasoning.txt +87 -0
  60. package/corpus/prose/wikipedia/LICENSE-NOTICE +94 -0
  61. package/corpus/prose/wikipedia/Language.txt +10 -0
  62. package/corpus/prose/wikipedia/Learning.txt +4 -0
  63. package/corpus/prose/wikipedia/Mammal.txt +3 -0
  64. package/corpus/prose/wikipedia/Memory.txt +5 -0
  65. package/corpus/prose/wikipedia/Milk.txt +1 -0
  66. package/corpus/prose/wikipedia/Mountain.txt +1 -0
  67. package/corpus/prose/wikipedia/Natural_language_processing.txt +211 -0
  68. package/corpus/prose/wikipedia/Ostrich.txt +2 -0
  69. package/corpus/prose/wikipedia/Owl.txt +2 -0
  70. package/corpus/prose/wikipedia/Penguin.txt +2 -0
  71. package/corpus/prose/wikipedia/Plant.txt +5 -0
  72. package/corpus/prose/wikipedia/Rain.txt +1 -0
  73. package/corpus/prose/wikipedia/Resource_Description_Framework.txt +184 -0
  74. package/corpus/prose/wikipedia/River.txt +1 -0
  75. package/corpus/prose/wikipedia/School.txt +8 -0
  76. package/corpus/prose/wikipedia/Sea.txt +1 -0
  77. package/corpus/prose/wikipedia/Semantic_Web.txt +114 -0
  78. package/corpus/prose/wikipedia/Semantic_reasoner.txt +29 -0
  79. package/corpus/prose/wikipedia/Snow.txt +5 -0
  80. package/corpus/prose/wikipedia/Sun.txt +5 -0
  81. package/corpus/prose/wikipedia/Teacher.txt +4 -0
  82. package/corpus/prose/wikipedia/Team.txt +3 -0
  83. package/corpus/prose/wikipedia/Text-based_game.txt +17 -0
  84. package/corpus/prose/wikipedia/Tool.txt +4 -0
  85. package/corpus/prose/wikipedia/Tree.txt +7 -0
  86. package/corpus/prose/wikipedia/Weather.txt +4 -0
  87. package/corpus/prose/wikipedia/Web_Ontology_Language.txt +133 -0
  88. package/corpus/prose/wikipedia/Wind.txt +8 -0
  89. package/corpus/prose/wikipedia/Writing.txt +5 -0
  90. package/corpus/wordnet/generate.mjs +6 -7
  91. package/package.json +31 -2
  92. package/src/adapters/corpus/conceptnet.mjs +1 -1
  93. package/src/adapters/graph-build.mjs +3 -3
  94. package/src/adapters/memory/blocks.mjs +2 -2
  95. package/src/adapters/memory/core.mjs +5 -5
  96. package/src/adapters/providers/bootstrap.mjs +1 -1
  97. package/src/adapters/providers/fixture.mjs +1 -1
  98. package/src/adapters/wink-model.mjs +1 -1
  99. package/src/adapters/wordnet-source.mjs +70 -0
  100. package/src/domain/answer-variants.json +1 -1
  101. package/src/domain/ask-vocab.mjs +2 -2
  102. package/src/domain/ask.mjs +4 -4
  103. package/src/domain/codegraph.mjs +3 -3
  104. package/src/domain/corpus-matrix.mjs +87 -0
  105. package/src/domain/grammar/ace.mjs +11 -11
  106. package/src/domain/grammar/lexicon.mjs +3 -3
  107. package/src/domain/inflect.mjs +67 -0
  108. package/src/domain/interpret/fuzzy.mjs +1 -1
  109. package/src/domain/interpret/merge.mjs +1 -1
  110. package/src/domain/interpret/normalize.mjs +1 -1
  111. package/src/domain/licences.mjs +68 -0
  112. package/src/domain/memory/capability.mjs +1 -1
  113. package/src/domain/memory/trust.mjs +2 -2
  114. package/src/domain/persona/codegen.mjs +123 -0
  115. package/src/domain/persona/examples.mjs +26 -0
  116. package/src/domain/persona/tiers.mjs +270 -0
  117. package/src/domain/publish-gate.mjs +41 -0
  118. package/src/domain/router/call-validator.mjs +1 -1
  119. package/src/domain/router/drive.mjs +3 -4
  120. package/src/domain/router/registry.mjs +12 -13
  121. package/src/domain/router/resolver.mjs +18 -5
  122. package/src/domain/router/results.mjs +3 -3
  123. package/src/domain/router/taught.mjs +4 -3
  124. package/src/domain/schemaorg/turtle.mjs +25 -0
  125. package/src/domain/semcor/parse.mjs +87 -0
  126. package/src/domain/syllogise.mjs +6 -6
  127. package/src/domain/version-stamp.mjs +36 -0
  128. package/src/domain/wordnet/yaml.mjs +133 -0
  129. package/src/services/chat-session.mjs +2 -2
  130. package/src/services/chat.mjs +2 -2
  131. package/src/services/cli-args.mjs +4 -4
  132. package/src/services/finish.mjs +1 -1
  133. package/src/services/ledger-viz.mjs +2 -3
  134. package/src/services/sessions.mjs +4 -4
  135. package/src/services/viz-theme.mjs +3 -4
  136. package/src/surfaces/web/memory-ask-browser.bundle.js +1 -18
  137. package/src/domain/router/guardrail.mjs +0 -116
@@ -0,0 +1,447 @@
1
+ Query Planning
2
+ Small. Fast. Reliable.
3
+ Choose any three.
4
+ Home
5
+ Menu
6
+ About
7
+ Documentation
8
+ Download
9
+ License
10
+ Support
11
+ Purchase
12
+ Search
13
+ About
14
+ Documentation
15
+ Download
16
+ Support
17
+ Purchase
18
+ Search Documentation
19
+ Search Changelog
20
+ Query Planning
21
+ Table Of Contents
22
+ 1. Searching
23
+ 1.1. Tables Without Indices
24
+ 1.2. Lookup By Rowid
25
+ 1.3. Lookup By Index
26
+ 1.4. Multiple Result Rows
27
+ 1.5. Multiple AND-Connected WHERE-Clause Terms
28
+ 1.6. Multi-Column Indices
29
+ 1.7. Covering Indexes
30
+ 1.8. OR-Connected Terms In The WHERE Clause
31
+ 2. Sorting
32
+ 2.1. Sorting By Rowid
33
+ 2.2. Sorting By Index
34
+ 2.3. Sorting By Covering Index
35
+ 3. Searching And Sorting At The Same Time
36
+ 3.1. Searching And Sorting With A Multi-Column Index
37
+ 3.2. Searching And Sorting With A Covering Index
38
+ 3.3. Partial Sorting Using An Index (a.k.a. Block Sorting)
39
+ 4. WITHOUT ROWID tables
40
+ Overview
41
+ The best feature of SQL (in all its implementations, not just SQLite)
42
+ is that it is a declarative language, not a procedural
43
+ language. When programming in SQL you tell the system what you
44
+ want to compute, not how to compute it. The task of figuring out
45
+ the how is delegated to the query planner subsystem within
46
+ the SQL database engine.
47
+ For any given SQL statement, there might be hundreds or thousands or
48
+ even millions of different algorithms of performing the operation. All
49
+ of these algorithms will get the correct answer, though some will run
50
+ faster than others.
51
+ The query planner is an
52
+ AI that
53
+ tries to pick the fastest and most efficient algorithm for each SQL
54
+ statement.
55
+ Most of the time, the query planner in SQLite does a good job.
56
+ However, the query planner needs indices to
57
+ work with.
58
+ These indices must normally be added by programmers.
59
+ Rarely, the query planner AI will make a suboptimal algorithm
60
+ choice.
61
+ In those cases, programmers may want to provide additional
62
+ hints to help the query planner do a better job.
63
+ This document provides background information about how the
64
+ SQLite query planner and query engine work.
65
+ Programmers can use this information to help create better
66
+ indexes, and provide hints to help the query planner when
67
+ needed.
68
+ Additional information is provided in the
69
+ SQLite query planner and
70
+ next generation query planner documents.
71
+ 1. Searching
72
+ 1.1. Tables Without Indices
73
+ Most tables in SQLite consist of zero or more rows with a unique integer
74
+ key (the rowid or INTEGER PRIMARY KEY ) followed by content.
75
+ (The exception is WITHOUT ROWID tables.)
76
+ The rows
77
+ are logically stored in order of increasing rowid. As an example, this
78
+ article uses a table named "FruitsForSale" which relates various fruits
79
+ to the state
80
+ where they are grown and their unit price at market. The schema is this:
81
+ With some (arbitrary) data, such a table might be logically stored on disk
82
+ as shown in figure 1:
83
+ Figure 1: Logical Layout Of Table "FruitsForSale"
84
+ In this example, the rowids are not
85
+ consecutive but they are ordered. SQLite usually creates rowids beginning
86
+ with one and increasing by one with each added row. But if rows are
87
+ deleted, gaps can appear in the sequence. And the application can control
88
+ the rowid assigned if desired, so that rows are not necessarily inserted
89
+ at the bottom. But regardless of what happens, the rowids are always
90
+ unique and in strictly ascending order.
91
+ Suppose you want to look up the price of peaches. The query would
92
+ be as follows:
93
+ To satisfy this query, SQLite reads every row out of the
94
+ table, checks to see if the "fruit" column has the value of "Peach" and if
95
+ so, outputs the "price" column from that row. The process is illustrated
96
+ by figure 2 below.
97
+ This algorithm is called a full table scan
98
+ since the entire content of the
99
+ table must be read and examined in order to find the one row of interest.
100
+ With a table of only 7 rows, a full table scan is acceptable,
101
+ but if the table contained 7 million rows, a full table scan might read
102
+ megabytes of content in order to find a single 8-byte number.
103
+ For that reason, one normally tries to avoid full table scans.
104
+ Figure 2: Full Table Scan
105
+ 1.2. Lookup By Rowid
106
+ One technique for avoiding a full table scan is to do lookups by
107
+ rowid (or by the equivalent INTEGER PRIMARY KEY ). To lookup the
108
+ price of peaches, one would query for the entry with a rowid of 4:
109
+ Since the information is stored in the table in rowid order, SQLite
110
+ can find the correct row using a binary search.
111
+ If the table contains N elements, the time required to look up the
112
+ desired row is proportional to logN rather than being proportional
113
+ to N as in a full table scan. If the table contains 10 million elements,
114
+ that means the query will be on the order of N/logN or about 1 million
115
+ times faster.
116
+ Figure 3: Lookup By Rowid
117
+ 1.3. Lookup By Index
118
+ The problem with looking up information by rowid is that you probably
119
+ do not care what the price of "item 4" is - you want to know the price
120
+ of peaches. And so a rowid lookup is not helpful.
121
+ To make the original query more efficient, we can add an index on the
122
+ "fruit" column of the "fruitsforsale" table like this:
123
+ An index is another table similar to the original "fruitsforsale" table
124
+ but with the content (the fruit column in this case) stored in front of the
125
+ rowid and with all rows in content order.
126
+ Figure 4 gives a logical view of the Idx1 index.
127
+ The "fruit" column is the primary key used to order the elements of the
128
+ table and the "rowid" is the secondary key used to break the tie when
129
+ two or more rows have the same "fruit". In the example, the rowid
130
+ has to be used as a tie-breaker for the "Orange" rows.
131
+ Notice that since the rowid
132
+ is always unique over all elements of the original table, the composite key
133
+ of "fruit" followed by "rowid" will be unique over all elements of the index.
134
+ Figure 4: An Index On The Fruit Column
135
+ This new index can be used to implement a faster algorithm for the
136
+ original "Price of Peaches" query.
137
+ The query starts by doing a binary search on the Idx1 index for entries
138
+ that have fruit='Peach'. SQLite can do this binary search on the Idx1 index
139
+ but not on the original FruitsForSale table because the rows in Idx1 are sorted
140
+ by the "fruit" column. Having found a row in the Idx1 index that has
141
+ fruit='Peach', the database engine can extract the rowid for that row.
142
+ Then the database engines does a second binary search
143
+ on the original FruitsForSale table to find the
144
+ original row that contains fruit='Peach'.
145
+ From the row in the FruitsForSale table,
146
+ SQLite can then extract the value of the price column.
147
+ This procedure is illustrated by figure 5 .
148
+ Figure 5: Indexed Lookup For The Price Of Peaches
149
+ SQLite has to do two binary searches to find the price of peaches using
150
+ the method show above. But for a table with a large number of rows, this
151
+ is still much faster than doing a full table scan.
152
+ 1.4. Multiple Result Rows
153
+ In the previous query the fruit='Peach' constraint narrowed the result
154
+ down to a single row. But the same technique works even if multiple
155
+ rows are obtained. Suppose we looked up the price of Oranges instead of
156
+ Peaches:
157
+ Figure 6: Indexed Lookup For The Price Of Oranges
158
+ In this case, SQLite still does a single binary search to find the first
159
+ entry of the index where fruit='Orange'. Then it extracts the rowid from
160
+ the index and uses that rowid to lookup the original table entry via
161
+ binary search and output the price from the original table. But instead
162
+ of quitting, the database engine then advances to the next row of index
163
+ to repeat the process for next fruit='Orange' entry. Advancing to the
164
+ next row of an index (or table) is much less costly than doing a binary
165
+ search since the next row is often located on the same database page as
166
+ the current row. In fact, the cost of advancing to the next row is so
167
+ cheap in comparison to a binary search that we usually ignore it. So
168
+ our estimate for the total cost of this query is 3 binary searches.
169
+ If the number of rows of output is K and the number of rows in the table
170
+ is N, then in general the cost of doing the query is proportional
171
+ to (K+1)*logN.
172
+ 1.5. Multiple AND-Connected WHERE-Clause Terms
173
+ Next, suppose that you want to look up the price of not just any orange,
174
+ but specifically California-grown oranges. The appropriate query would
175
+ be as follows:
176
+ Figure 7: Indexed Lookup Of California Oranges
177
+ One approach to this query is to use the fruit='Orange' term of the WHERE
178
+ clause to find all rows dealing with oranges, then filter those rows
179
+ by rejecting any that are from states other than California. This
180
+ process is shown by figure 7 above. This is a perfectly
181
+ reasonable approach in most cases. Yes, the database engine did have
182
+ to do an extra binary search for the Florida orange row that was
183
+ later rejected, so it was not as efficient as we might hope, though
184
+ for many applications it is efficient enough.
185
+ Suppose that in addition to the index on "fruit" there was also
186
+ an index on "state".
187
+ Figure 8: Index On The State Column
188
+ The "state" index works just like the "fruit" index in that it is a
189
+ new table with an extra column in front of the rowid and sorted by
190
+ that extra column as the primary key. The only difference is that
191
+ in Idx2, the first column is "state" instead of "fruit" as it is with
192
+ Idx1. In our example data set, there is more redundancy in the "state"
193
+ column and so there are more duplicate entries. The ties are still
194
+ resolved using the rowid.
195
+ Using the new Idx2 index on "state", SQLite has another option for
196
+ lookup up the price of California oranges: it can look up every row
197
+ that contains fruit from California and filter out those rows that
198
+ are not oranges.
199
+ Figure 9: Indexed Lookup Of California Oranges
200
+ Using Idx2 instead of Idx1 causes SQLite to examine a different set of
201
+ rows, but it gets the same answer in the end (which is very important -
202
+ remember that indices should never change the answer, only help SQLite to
203
+ get to the answer more quickly) and it does the same amount of work.
204
+ So the Idx2 index did not help performance in this case.
205
+ The last two queries take the same amount of time, in our example.
206
+ So which index, Idx1 or Idx2, will SQLite choose? If the
207
+ ANALYZE command has been run on the database, so that SQLite has
208
+ had an opportunity to gather statistics about the available indices,
209
+ then SQLite will know that the Idx1 index usually narrows the search
210
+ down to a single item (our example of fruit='Orange' is the exception
211
+ to this rule) whereas the Idx2 index will normally only narrow the
212
+ search down to two rows. So, if all else is equal, SQLite will
213
+ choose Idx1 with the hope of narrowing the search to as small
214
+ a number of rows as possible. This choice is only possible because
215
+ of the statistics provided by ANALYZE . If ANALYZE has not been
216
+ run then the choice of which index to use is arbitrary.
217
+ 1.6. Multi-Column Indices
218
+ To get the maximum performance out of a query with multiple AND-connected
219
+ terms in the WHERE clause, you really want a multi-column index with
220
+ columns for each of the AND terms. In this case we create a new index
221
+ on the "fruit" and "state" columns of FruitsForSale:
222
+ Figure 1: A Two-Column Index
223
+ A multi-column index follows the same pattern as a single-column index;
224
+ the indexed columns are added in front of the rowid. The only difference
225
+ is that now multiple columns are added. The left-most column is the
226
+ primary key used for ordering the rows in the index. The second column is
227
+ used to break ties in the left-most column. If there were a third column,
228
+ it would be used to break ties for the first two columns. And so forth for
229
+ all columns in the index. Because rowid is guaranteed
230
+ to be unique, every row of the index will be unique even if all of the
231
+ content columns for two rows are the same. That case does not happen
232
+ in our sample data, but there is one case (fruit='Orange') where there
233
+ is a tie on the first column which must be broken by the second column.
234
+ Given the new multi-column Idx3 index, it is now possible for SQLite
235
+ to find the price of California oranges using only 2 binary searches:
236
+ Figure 11: Lookup Using A Two-Column Index
237
+ With the Idx3 index on both columns that are constrained by the WHERE clause,
238
+ SQLite can do a single binary search against Idx3 to find the one rowid
239
+ for California oranges, then do a single binary search to find the price
240
+ for that item in the original table. There are no dead-ends and no
241
+ wasted binary searches. This is a more efficient query.
242
+ Note that Idx3 contains all the same information as the original
243
+ Idx1 . And so if we have Idx3, we do not really need Idx1
244
+ any more. The "price of peaches" query can be satisfied using Idx3
245
+ by simply ignoring the "state" column of Idx3:
246
+ Figure 12: Single-Column Lookup On A Multi-Column Index
247
+ Hence, a good rule of thumb is that your database schema should never
248
+ contain two indices where one index is a prefix of the other. Drop the
249
+ index with fewer columns. SQLite will still be able to do efficient
250
+ lookups with the longer index.
251
+ 1.7. Covering Indexes
252
+ The "price of California oranges" query was made more efficient through
253
+ the use of a two-column index. But SQLite can do even better with a
254
+ three-column index that also includes the "price" column:
255
+ Figure 13: A Covering Index
256
+ This new index contains all the columns of the original FruitsForSale table that
257
+ are used by the query - both the search terms and the output. We call
258
+ this a "covering index". Because all of the information needed is in
259
+ the covering index, SQLite never needs to consult the original table
260
+ in order to find the price.
261
+ Figure 14: Query Using A Covering Index
262
+ Hence, by adding extra "output" columns onto the end of an index, one
263
+ can avoid having to reference the original table and thereby
264
+ cut the number of binary searches for a query in half. This is a
265
+ constant-factor improvement in performance (roughly a doubling of
266
+ the speed). But on the other hand, it is also just a refinement;
267
+ A two-fold performance increase is not nearly as dramatic as the
268
+ one-million-fold increase seen when the table was first indexed.
269
+ And for most queries, the difference between 1 microsecond and
270
+ 2 microseconds is unlikely to be noticed.
271
+ 1.8. OR-Connected Terms In The WHERE Clause
272
+ Multi-column indices only work if the constraint terms in the WHERE
273
+ clause of the query are connected by AND.
274
+ So Idx3 and Idx4 are helpful when the search is for items that
275
+ are both Oranges and grown in California, but neither index would
276
+ be that useful if we wanted all items that were either oranges
277
+ or are grown in California.
278
+ When confronted with OR-connected terms in a WHERE clause, SQLite
279
+ examines each OR term separately and tries to use an index to
280
+ find the rowids associated with each term.
281
+ It then takes the union of the resulting rowid sets to find
282
+ the end result. The following figure illustrates this process:
283
+ Figure 15: Query With OR Constraints
284
+ The diagram above implies that SQLite computes all of the rowids first
285
+ and then combines them with a union operation before starting to do
286
+ rowid lookups on the original table. In reality, the rowid lookups
287
+ are interspersed with rowid computations. SQLite uses one index at
288
+ a time to find rowids while remembering which rowids it has seen
289
+ before so as to avoid duplicates. That is just an implementation
290
+ detail, though. The diagram, while not 100% accurate, provides a good
291
+ overview of what is happening.
292
+ In order for the OR-by-UNION technique shown above to be useful, there
293
+ must be an index available that helps resolve every OR-connected term
294
+ in the WHERE clause. If even a single OR-connected term is not indexed,
295
+ then a full table scan would have to be done in order to find the rowids
296
+ generated by the one term, and if SQLite has to do a full table scan, it
297
+ might as well do it on the original table and get all of the results in
298
+ a single pass without having to mess with union operations and follow-on
299
+ binary searches.
300
+ One can see how the OR-by-UNION technique could also be leveraged to
301
+ use multiple indices on queries where the WHERE clause has terms connected
302
+ by AND, by using an intersect operator in place of union. Many SQL
303
+ database engines will do just that. But the performance gain over using
304
+ just a single index is slight and so SQLite does not implement that technique
305
+ at this time. However, a future version SQLite might be enhanced to support
306
+ AND-by-INTERSECT.
307
+ 2. Sorting
308
+ SQLite (like all other SQL database engines) can also use indices to
309
+ satisfy the ORDER BY clauses in a query, in addition to expediting
310
+ lookup. In other words, indices can be used to speed up sorting as
311
+ well as searching.
312
+ When no appropriate indices are available, a query with an ORDER BY
313
+ clause must be sorted as a separate step. Consider this query:
314
+ SQLite processes this by gathering all the output of the query and then
315
+ running that output through a sorter.
316
+ Figure 16: Sorting Without An Index
317
+ If the number of output rows is K, then the time needed to sort is
318
+ proportional to KlogK. If K is small, the sorting time is usually
319
+ not a factor, but in a query such as the above where K==N, the time
320
+ needed to sort can be much greater than the time needed to do a
321
+ full table scan. Furthermore, the entire output is accumulated in
322
+ temporary storage (which might be either in main memory or on disk,
323
+ depending on various compile-time and run-time settings)
324
+ which can mean that a lot of temporary storage is required to complete
325
+ the query.
326
+ 2.1. Sorting By Rowid
327
+ Because sorting can be expensive, SQLite works hard to convert ORDER BY
328
+ clauses into no-ops. If SQLite determines that output will
329
+ naturally appear in the order specified, then no sorting is done.
330
+ So, for example, if you request the output in rowid order, no sorting
331
+ will be done:
332
+ Figure 17: Sorting By Rowid
333
+ You can also request a reverse-order sort like this:
334
+ SQLite will still omit the sorting step. But in order for output to
335
+ appear in the correct order, SQLite will do the table scan starting at
336
+ the end and working toward the beginning, rather than starting at the
337
+ beginning and working toward the end as shown in
338
+ figure 17 .
339
+ 2.2. Sorting By Index
340
+ Of course, ordering the output of a query by rowid is seldom useful.
341
+ Usually one wants to order the output by some other column.
342
+ If an index is available on the ORDER BY column, that index can be used
343
+ for sorting. Consider the request for all items sorted by "fruit":
344
+ Figure 18: Sorting With An Index
345
+ The Idx1 index is scanned from top to bottom (or from bottom to top if
346
+ "ORDER BY fruit DESC" is used) in order to find the rowids for each item
347
+ in order by fruit. Then for each rowid, a binary search is done to lookup
348
+ and output that row. In this way, the output appears in the requested order
349
+ without the need to gather the entire output and sort it using a separate step.
350
+ But does this really save time? The number of steps in the
351
+ original indexless sort is proportional to NlogN since
352
+ that is how much time it takes to sort N rows. But when we use Idx1 as
353
+ shown here, we have to do N rowid lookups which take logN time each, so
354
+ the total time of NlogN is the same!
355
+ SQLite uses a cost-based query planner. When there are two or more ways
356
+ of solving the same query, SQLite tries to estimate the total amount of
357
+ time needed to run the query using each plan, and then uses the plan with
358
+ the lowest estimated cost. A cost is computed mostly from the estimated
359
+ time, and so this case could go either way depending on the table size and
360
+ what WHERE clause constraints were available, and so forth. But generally
361
+ speaking, the indexed sort would probably be chosen, if for no other
362
+ reason, because it does not need to accumulate the entire result set in
363
+ temporary storage before sorting and thus uses much less temporary storage.
364
+ 2.3. Sorting By Covering Index
365
+ If a covering index can be used for a query, then the multiple rowid lookups
366
+ can be avoided and the cost of the query drops dramatically.
367
+ Figure 19: Sorting With A Covering Index
368
+ With a covering index, SQLite can simply walk the index from one end to the
369
+ other and deliver the output in time proportional to N and without having to
370
+ allocate a large buffer to hold the result set.
371
+ 3. Searching And Sorting At The Same Time
372
+ The previous discussion has treated searching and sorting as separate
373
+ topics. But in practice, it is often the case that one wants to search
374
+ and sort at the same time. Fortunately, it is possible to do this
375
+ using a single index.
376
+ 3.1. Searching And Sorting With A Multi-Column Index
377
+ Suppose we want to find the prices of all kinds of oranges sorted in
378
+ order of the state where they are grown. The query is this:
379
+ The query contains both a search restriction in the WHERE clause
380
+ and a sort order in the ORDER BY clause. Both the search and the sort
381
+ can be accomplished at the same time using the two-column index Idx3.
382
+ Figure 20: Search And Sort By Multi-Column Index
383
+ The query does a binary search on the index to find the subset of rows
384
+ that have fruit='Orange'. (Because the fruit column is the left-most column
385
+ of the index and the rows of the index are in sorted order, all such
386
+ rows will be adjacent.) Then it scans the matching index rows from top to
387
+ bottom to get the rowids for the original table, and for each rowid does
388
+ a binary search on the original table to find the price.
389
+ You will notice that there is no "sort" box anywhere in the above diagram.
390
+ The ORDER BY clause of the query has become a no-op. No sorting has to be
391
+ done here because the output order is by the state column and the state
392
+ column also happens to be the first column after the fruit column in the
393
+ index. So, if we scan entries of the index that have the same value for
394
+ the fruit column from top to bottom, those index entries are guaranteed to
395
+ be ordered by the state column.
396
+ 3.2. Searching And Sorting With A Covering Index
397
+ A covering index can also be used to search and sort at the same time.
398
+ Consider the following:
399
+ Figure 21: Search And Sort By Covering Index
400
+ As before, SQLite does a single binary search
401
+ for the range of rows in the covering
402
+ index that satisfy the WHERE clause, then scans that range from top to
403
+ bottom to get the desired results.
404
+ The rows that satisfy the WHERE clause are guaranteed to be adjacent
405
+ since the WHERE clause is an equality constraint on the left-most
406
+ column of the index. And by scanning the matching index rows from
407
+ top to bottom, the output is guaranteed to be ordered by state since the
408
+ state column is the very next column to the right of the fruit column.
409
+ And so the resulting query is very efficient.
410
+ SQLite can pull a similar trick for a descending ORDER BY:
411
+ The same basic algorithm is followed, except this time the matching rows
412
+ of the index are scanned from bottom to top instead of from top to bottom,
413
+ so that the states will appear in descending order.
414
+ 3.3. Partial Sorting Using An Index (a.k.a. Block Sorting)
415
+ Sometimes only part of an ORDER BY clause can be satisfied using indexes.
416
+ Consider, for example, the following query:
417
+ If the covering index is used for the scan, the "fruit" column will appear
418
+ naturally in the correct order, but when there are two or more rows with
419
+ the same fruit, the price might be out of order. When this occurs, SQLite
420
+ does many small sorts, one sort for each distinct value of fruit, rather
421
+ than one large sort. Figure 22 below illustrates the concept.
422
+ Figure 22: Partial Sort By Index
423
+ In the example, instead of a single sort of 7 elements, there
424
+ are 5 sorts of one-element each and 1 sort of 2 elements for the
425
+ case of fruit=='Orange'.
426
+ The advantages of doing many smaller sorts instead of a single large sort
427
+ are:
428
+ Multiple small sorts collectively use fewer CPU cycles than a single
429
+ large sort.
430
+ Each small sort is run independently, meaning that much less information
431
+ needs to be kept in temporary storage at any one time.
432
+ Those columns of the ORDER BY that are already in the correct order
433
+ due to indexes can be omitted from the sort key, further reducing
434
+ storage requirements and CPU time.
435
+ Output rows can be returned to the application as each small sort
436
+ completes, and well before the table scan is complete.
437
+ If a LIMIT clause is present, it might be possible to avoid scanning
438
+ the entire table.
439
+ Because of these advantages, SQLite always tries to do a partial sort using an
440
+ index even if a complete sort by index is not possible.
441
+ 4. WITHOUT ROWID tables
442
+ The basic principles described above apply to both ordinary rowid tables
443
+ and WITHOUT ROWID tables.
444
+ The only difference is that the rowid column that serves as the key for
445
+ tables and that appears as the right-most term in indexes is replaced by
446
+ the PRIMARY KEY.
447
+ This page was last updated on 2026-03-22 10:09:38Z
@@ -0,0 +1,41 @@
1
+ SQLite Is Transactional
2
+ Small. Fast. Reliable.
3
+ Choose any three.
4
+ Home
5
+ Menu
6
+ About
7
+ Documentation
8
+ Download
9
+ License
10
+ Support
11
+ Purchase
12
+ Search
13
+ About
14
+ Documentation
15
+ Download
16
+ Support
17
+ Purchase
18
+ Search Documentation
19
+ Search Changelog
20
+ SQLite is Transactional
21
+ A transactional database is one in which all changes and queries
22
+ appear to be
23
+ Atomic, Consistent, Isolated, and Durable
24
+ ( ACID ).
25
+ SQLite implements
26
+ serializable
27
+ transactions that are atomic, consistent, isolated, and durable,
28
+ even if the transaction is interrupted by a program crash, an
29
+ operating system crash, or a power failure to the computer.
30
+ We here restate and amplify the previous sentence for emphasis:
31
+ All changes within a single transaction in SQLite either occur
32
+ completely or not at all, even if the act of writing the change
33
+ out to the disk is interrupted by
34
+ a program crash,
35
+ an operating system crash, or
36
+ a power failure.
37
+ The claim of the previous paragraph is extensively checked in the
38
+ SQLite regression test suite using a special test harness that
39
+ simulates the effects on a database file of operating system crashes
40
+ and power failures.
41
+ Additional information