Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch branch-3.8.8 Excluding Merge-Ins
This is equivalent to a diff from b800b2aa94 to 973dd7c44b
2015-03-23
| ||
13:25 | Merge in fixes from the 3.8.8 branch. (check-in: a17575cedc user: drh tags: trunk) | |
2015-03-16
| ||
22:22 | Fix typos in the FAQ. (Leaf check-in: 973dd7c44b user: drh tags: branch-3.8.8) | |
20:37 | Fix a typo in the queryplanner.html document. (check-in: 94ffc3e5cb user: drh tags: branch-3.8.8) | |
2015-02-17
| ||
19:09 | Pull in the whentouse.html updates without waiting for the next release. (check-in: 1dfc552b2a user: drh tags: branch-3.8.8) | |
17:21 | Enhancements to the whentouse.html document. (check-in: ddb8a3924e user: drh tags: trunk) | |
2015-02-11
| ||
17:28 | Add a note to the date-time function documentation to say that the "s" at the end of modifiers like "days" is optional. (check-in: b800b2aa94 user: drh tags: trunk) | |
2015-02-03
| ||
06:14 | Fix a typo in the index_info pragma documentation. (check-in: 49266aeb5b user: drh tags: trunk) | |
Added pages/aff_short.in.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | <tcl>hd_keywords *affshort {file-format benefits}</tcl> <title>Benefits of SQLite As A File Format</title> <h1 align="center"> SQLite As An Application File Format </h1> <p><i>(Note: The current page is a brief summary of why SQLite makes a good application file format. The topic is considered at greater detail in a [application file-format | separate technical note].)</i></p> <p> SQLite has been used with great success as the on-disk file format for desktop applications such as version control systems, financial analysis tools, media cataloging and editing suites, CAD packages, record keeping programs, and so forth. The traditional File/Open operation calls sqlite3_open() to attach to the database file. Updates happen automatically as application content is revised so the File/Save menu option becomes superfluous. The File/Save_As menu option can be implemented using the [backup API]. </p> <p> There are many advantages to using SQLite as an application file format, including: </p> <ol type="1"> <li><b>Better performance</b> <ul> <li> The application only has to load the data it needs, rather than reading the entire file and holding a complete parse in memory. <li> Small edits only overwrite the parts of the file that change, reducing write time and wear on SSD drives. <li> In many cases, loading content from an SQLite database is faster than reading individual files from disk. See [Internal Versus External BLOBs]. </ul> <li><b>Reduced application cost and complexity</b> <ul> <li> No application file I/O code to write and debug. <li> Content can be accessed and updated using concise SQL queries instead of lengthy and error-prone procedural routines. <li> The file format can be extended in future releases simply by adding new tables and/or column, preserving backwards compatibility. <li> Applications can leverage the [full-text search] and [RTREE] indexes. <li> Performance problems can often be resolved, even late in the development cycle, using [CREATE INDEX], avoiding costly redesign, rewrite, and retest efforts. </ul> <li><b>Portability</b> <ul> <li> The application file is portable across all operating systems, 32-bit and 64-bit and big- and little-endian architectures. <li> A federation of programs, perhaps all written in different programming languages, can access the same application file with no compatibility concerns. <li> Multiple processes can attach to the same application file and can read and write without interfering with each another. <li> Diverse content which might otherwise be stored as a "pile-of-files" is encapsulated into a single disk file for simpler transport via scp/ftp, USB stick, and/or email attachment. </ul> <li><b>Reliability</b> <ul> <li> Content can be updated continuously and atomically so that little or no work is lost in a power failure or crash. <li> Bugs are far less likely in SQLite than in custom-written file I/O code. <li> SQL queries are many times smaller than the equivalent procedural code, and since the number of bugs per line of code is roughly constant, this means fewer bugs overall. </ul> <li><b>Accessibility</b> <ul> <li> SQLite database content can be viewed using a wide variety third-party tools. <li> Content stored in an SQLite database is more likely to be recoverable decades in the future, long after all traces of the original application have been lost. Data lives longer than code. </ul> </ol> <p> SQLite allows database files to have any desired filename extension, so an application can choose a custom filename extension for its own use, if desired. The [application_id pragma] can be used to set an "Application ID" integer in the database file so that tools like [http://www.darwinsys.com/file/ | file(1)] can determine that the file is associated with your application and is not just a generic SQL database.</p> |
Changes to pages/capi3ref.in.
1 | <title>C/C++ Interface For SQLite Version 3</title> | < < < | 1 2 3 4 5 6 7 8 | <title>C/C++ Interface For SQLite Version 3</title> <tcl> set in [open sqlite3.h] set title {} ;# title of a section of interface definition set type {} ;# one of: constant datatype function set body {} ;# human-readable description set code {} ;# C code of the definition set phase 0 ;# Phase used by the parser |
︙ | ︙ | |||
235 236 237 238 239 240 241 | hd_open_aux c3ref/intro.html hd_header Introduction hd_enable_main 0 hd_keywords *capi3ref {C-language Interface} </tcl> | > | > < | | > | | | < < < | | | < < | < | | | < | | > | > | < | > | | | | < < < | < < < < | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | hd_open_aux c3ref/intro.html hd_header Introduction hd_enable_main 0 hd_keywords *capi3ref {C-language Interface} </tcl> <h1 align="center"> C-language Interface Specification for SQLite </h1> <p>These pages are intended to be precise and detailed specification. For a tutorial introduction, see instead: <ul> <li>[quickstart | SQLite In 3 Minutes Or Less] and/or <li>the [cintro | Introduction To The SQLite C/C++ Interface]. </ul> This same content is also available as a <a href="../capi3ref.html">single large HTML file</a>. </p> <p>The SQLite interface elements can be grouped into three categories:</p> <ol> <li><p><a href="objlist.html"><b>List Of Objects.</b></a> This is a list of all abstract objects and datatypes used by the SQLite library. There are couple dozen objects in total, but the two most important objects are: A database connection object [sqlite3], and the prepared statement object [sqlite3_stmt].</p></li> <li><p><a href="constlist.html"><b>List Of Constants.</b></a> This is a list of numeric constants used by SQLite and represented by #defines in the sqlite3.h header file. These constants are things such as numeric [result codes] from various interfaces (ex: [SQLITE_OK]) or flags passed into functions to control behavior (ex: [SQLITE_OPEN_READONLY]).</p></li> <li><p><a href="funclist.html"><b>List Of Functions.</b></a> This is a list of all functions and methods operating on the <a href="objlist.html">objects</a> and using and/or returning <a href="constlist.html">constants</a>. There are many functions, but most applications only use a handful. </p></li> </ol> <tcl> hd_close_aux hd_enable_main 1 </tcl> <h1 align="center"> C-language Interface Specification for SQLite </h1> <p>This page is intended to be a precise and detailed specification. For a tutorial introductions, see instead: <ul> <li>[quickstart | SQLite In 3 Minutes Or Less] and/or <li>the [cintro | Introduction To The SQLite C/C++ Interface]. </ul> This same content is also available split out into <a href="c3ref/intro.html">lots of small pages</a>.</p> <hr> <tcl> # Find the preferred keyword for a page given a list of # acceptable keywords. # |
︙ | ︙ | |||
393 394 395 396 397 398 399 | } hd_open_aux c3ref/objlist.html hd_header {List Of SQLite Objects} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> | | < < < | > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | } hd_open_aux c3ref/objlist.html hd_header {List Of SQLite Objects} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> <h2>List Of Objects:</h2> <tcl> output_list 3 [lsort -nocase $objlist] hd_enable_main 0 hd_putsnl {<p>Other lists: <a href="constlist.html">Constants</a> and <a href="funclist.html">Functions</a> and <a href="../rescode.html">Result Codes</a>.} hd_close_aux hd_enable_main 1 hd_putsnl {<hr>} # Do a table of contents for constants # set clist {} |
︙ | ︙ | |||
428 429 430 431 432 433 434 | } hd_open_aux c3ref/constlist.html hd_header {List Of SQLite Constants} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> | | | < < | > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | } hd_open_aux c3ref/constlist.html hd_header {List Of SQLite Constants} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> <h2>List Of Constants:</h2> <p>Also available: [error codes|list of error codes]</p> <tcl> set clist [lsort -index 1 $clist] output_list 2 $clist hd_enable_main 0 hd_putsnl {<p>Other lists: <a href="objlist.html">Objects</a> and <a href="funclist.html">Functions</a> and <a href="../rescode.html">Result Codes</a>.</p>} hd_enable_main 1 hd_close_aux hd_putsnl {<hr>} # Do a table of contents for functions # |
︙ | ︙ | |||
466 467 468 469 470 471 472 | hd_open_aux c3ref/funclist.html hd_header {List Of SQLite Functions} hd_keywords *capi3ref_funclist {C-API function list} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> | | | > | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | hd_open_aux c3ref/funclist.html hd_header {List Of SQLite Functions} hd_keywords *capi3ref_funclist {C-API function list} hd_enable_main 0 hd_putsnl {<a href="intro.html"><h2>SQLite C Interface</h2></a>} hd_enable_main 1 </tcl> <h2>List Of Functions:</h2> <p>Note: Functions marked with "[experimental | <small><i>(exp)</i></small>]" are [experimental] and functions marked with [deprecated | <small><i>(obs)</i></small>] are [deprecated].</p> <tcl> set funclist [lsort -index 1 $funclist] output_list 3 $funclist hd_enable_main 0 hd_putsnl {<p>Other lists: <a href="constlist.html">Constants</a> and <a href="objlist.html">Objects</a> and <a href="../rescode.html">Result Codes</a></p>} hd_enable_main 1 hd_close_aux hd_putsnl {<hr>} # Convert a fragment text label into a fragment name # proc hd_fragname {lbl} { |
︙ | ︙ |
Changes to pages/changes.in.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | set nChng 0 proc chng {date desc {options {}}} { global nChng aChng set aChng($nChng) [list $date $desc $options] incr nChng } chng {2015-01-30 (3.8.8.2)} { <li>Enhance [sqlite3_wal_checkpoint_v2(TRUNCATE)] interface so that it truncates the WAL file even if there is no checkpoint work to be done. <li>SQLITE_SOURCE_ID: "2015-01-30 14:30:45 7757fc721220e136620a89c9d28247f28bbbc098" <li>SHA1 for sqlite3.c: 85ce79948116aa9a087ec345c9d2ce2c1d3cd8af | > > > > > > > > > > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | set nChng 0 proc chng {date desc {options {}}} { global nChng aChng set aChng($nChng) [list $date $desc $options] incr nChng } chng {2015-02-25 (3.8.8.3)} { <li>Fix a bug (ticket [https://www.sqlite.org/src/info/2326c258d02ead33|2326c258d02ead33]) that can lead to incorrect results if the qualifying constraint of a [partial index] appears in the ON clause of a LEFT JOIN. <li>Added the ability to link against the "[https://github.com/antirez/linenoise|linenoise]" command-line editing library in unix builds of the [command-line shell]. <li>SQLITE_SOURCE_ID: "2015-02-25 13:29:11 9d6c1880fb75660bbabd693175579529785f8a6b" <li>SHA1 for sqlite3.c: 74ee38c8c6fd175ec85a47276dfcefe8a262827a } {patchagainst 1 patchagainst 2 patchagainst 3} chng {2015-01-30 (3.8.8.2)} { <li>Enhance [sqlite3_wal_checkpoint_v2(TRUNCATE)] interface so that it truncates the WAL file even if there is no checkpoint work to be done. <li>SQLITE_SOURCE_ID: "2015-01-30 14:30:45 7757fc721220e136620a89c9d28247f28bbbc098" <li>SHA1 for sqlite3.c: 85ce79948116aa9a087ec345c9d2ce2c1d3cd8af |
︙ | ︙ |
Changes to pages/cintro.in.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 | } incr n 1 hd_puts "<h$n>$num $name</h$n>" } hd_keywords {*cintro} HEADING 0 {An Introduction To The SQLite C/C++ Interface} </tcl> | > > > | > > > > > > | > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | } incr n 1 hd_puts "<h$n>$num $name</h$n>" } hd_keywords {*cintro} HEADING 0 {An Introduction To The SQLite C/C++ Interface} HEADING 1 {Executive Summary} </tcl> <p>The following two objects and eight methods comprise the essential elements of the SQLite interface: <table border="0" cellpadding="0"> <tr> <td valign="top"><b>[sqlite3]</b></td><td> </td> <td>The database connection object. Created by [sqlite3_open()] and destroyed by [sqlite3_close()].</td> </tr> <tr> <td valign="top"><b>[sqlite3_stmt]</b></td><td> <td>The prepared statement object. Created by [sqlite3_prepare()] and destroyed by [sqlite3_finalize()].</td> </tr> <tr> <td valign="top"><b>[sqlite3_open()]</b></td><td> <td>Open a connection to a new or existing SQLite database. The constructor for [sqlite3].</td> </tr> <tr> <td valign="top"><b>[sqlite3_prepare()]</b></td><td> <td>Compile SQL text into byte-code that will do the work of querying or updating the database. The constructor for [sqlite3_stmt].</td> </tr> <tr> <td valign="top"><b>[sqlite3_bind_int|sqlite3_bind()]</td><td> <td>Store application data into [parameters] of the original SQL.</td> </tr> <tr> <td valign="top"><b>[sqlite3_step()]</td><td> <td>Advance an [sqlite3_stmt] to the next result row or to completion.</td> </tr> <tr> <td valign="top"><b>[sqlite3_column_int|sqlite3_column()]</td><td> <td>Column values in the current result row for an [sqlite3_stmt].</td> </tr> <tr> <td valign="top"><b>[sqlite3_finalize()]</td><td> <td>Destructor for [sqlite3_stmt].</td> </tr> <tr> <td valign="top"><b>[sqlite3_close()]</td><td> <td>Destructor for [sqlite3].</td> </tr> <tr> <td valign="top"><b>[sqlite3_exec()]</td><td> <td>A wrapper function that does [sqlite3_prepare()], [sqlite3_step()], [sqlite3_column_int|sqlite3_column()], and [sqlite3_finalize()] for a string of one or more SQL statements.</td> </tr> </table> <tcl>HEADING 1 {Introduction}</tcl> <p> Early versions of SQLite were very easy to learn since they only supported five C/C++ interfaces. But as SQLite has grown in capability, new C/C++ interfaces have been added so that now there are over 200 distinct APIs. This can be overwhelming to a new programmer. Fortunately, most of the C/C++ interfaces in SQLite are very specialized and never need to be considered. Despite having so many entry points, the core API is still simple to learn and easy to code to. This article aims to provide all of the background information needed to easily understand how SQLite works. </p> <p> A separate document, [capi3ref | The SQLite C/C++ Interface], provides detailed specifications for all C/C++ APIs for SQLite. Once the reader understands the basic principles of operation for SQLite, [capi3ref | that document] should be used as a reference guide. This article is intended as introduction only and is neither a complete nor authoritative reference for the SQLite API. </p> |
︙ | ︙ |
Changes to pages/compile.in.
︙ | ︙ | |||
524 525 526 527 528 529 530 | </tcl> <a name="enablefeatures"></a> <h2>1.5 Options To Enable Features Normally Turned Off</h2> <tcl> COMPILE_OPTION {SQLITE_ALLOW_URI_AUTHORITY} { | | | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | </tcl> <a name="enablefeatures"></a> <h2>1.5 Options To Enable Features Normally Turned Off</h2> <tcl> COMPILE_OPTION {SQLITE_ALLOW_URI_AUTHORITY} { [URI filenames] normally throws an error if the authority section is not either empty or "localhost". However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way. <p> Some future versions of SQLite may change to enable this feature by default. |
︙ | ︙ |
Changes to pages/faq.in.
︙ | ︙ | |||
520 521 522 523 524 525 526 | experience by billions of users.</p> <p>That said, there are a number of things that external programs or bugs in your hardware or OS can do to corrupt a database file. See <a href="howtocorrupt.html">How To Corrupt An SQLite Database File</a> for further information. | | | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | experience by billions of users.</p> <p>That said, there are a number of things that external programs or bugs in your hardware or OS can do to corrupt a database file. See <a href="howtocorrupt.html">How To Corrupt An SQLite Database File</a> for further information. <p>You can use <a href="pragma.html#pragma_integrity_check">PRAGMA integrity_check</a> to do a thorough but time intensive test of the database integrity.</p> <p>You can use <a href="pragma.html#pragma_quick_check">PRAGMA quick_check</a> to do a faster but less thorough test of the database integrity.</p> <p>Depending how badly your database is corrupted, you may be able to recover some of the data by using the CLI to dump the schema and contents to a file and then recreate. Unfortunately, once humpty-dumpty falls off the wall, it is generally not possible to put him back together again.</p> } |
︙ | ︙ |
Changes to pages/features.in.
1 2 3 4 5 6 7 8 9 10 | <title>Features Of SQLite</title> <h1 align=center>Features Of SQLite</h1> <p><ul> <li><a href="transactional.html">Transactions</a> are atomic, consistent, isolated, and durable (ACID) even after system crashes and power failures.</li> <li><a href="zeroconf.html">Zero-configuration</a> - no setup or administration needed.</li> | | > > | | | > > > > > > > < < < < < < < > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <title>Features Of SQLite</title> <h1 align=center>Features Of SQLite</h1> <p><ul> <li><a href="transactional.html">Transactions</a> are atomic, consistent, isolated, and durable (ACID) even after system crashes and power failures.</li> <li><a href="zeroconf.html">Zero-configuration</a> - no setup or administration needed.</li> <li><a href="lang.html">Full SQL implementation</a> with advanced features like [partial indexes] and [common table expressions]. (<a href="omitted.html">Omitted features</a>)</li> <li>A complete database is stored in a <a href="onefile.html">single cross-platform disk file</a>. Great for use as an [application file format].</li> <li>Supports terabyte-sized databases and gigabyte-sized strings and blobs. (See <a href="limits.html">limits.html</a>.) <li>Small code [footprint]: less than 500KiB fully configured or much less with optional features omitted.</li> <li>Simple, easy to use <a href="cintro.html">API</a>.</li> <li>Written in ANSI-C. <a href="tclsqlite.html">TCL bindings</a> included. Bindings for dozens of other languages available separately.</li> <li>Well-commented source code with [test coverage |100% branch test coverage].</li> <li>Available as a <a href="amalgamation.html">single ANSI-C source-code file</a> that is [how to compile|easy to compile] and hence is easy to add into a larger project. <li><a href="selfcontained.html">Self-contained</a>: no external dependencies.</li> <li>Cross-platform: Android, *BSD, iOS, Linux, Mac, Solaris, VxWorks, and Windows (Win32, WinCE, WinRT) are supported out of the box. Easy to port to other systems. <li>Sources are in the <a href="copyright.html">public domain</a>. Use for any purpose.</li> <li>Comes with a standalone [command-line interface] (CLI) client that can be used to administer SQLite databases.</li> </ul> </p> <h2>Suggested Uses For SQLite:</h2> <p><ul> <li><p><b>Database For The Internet Of Things.</b> SQLite is popular choice for the database engine in cellphones, PDAs, MP3 players, set-top boxes, and other electronic gadgets. SQLite has a small code footprint, makes efficient use of memory, disk space, and disk bandwidth, is highly reliable, and requires no maintenance from a Database Administrator.</p></li> <li><p><b>Application File Format.</b> Rather than using fopen() to write XML, JSON, CSV, or some proprietary format into disk files used by your application, use an SQLite database. You'll avoid having to write and troubleshoot a parser, your data will be more easily accessible and cross-platform, and your updates will be transactional. ([application file-format | more...])</p></li> <li><p><b>Website Database.</b> Because it requires no configuration and stores information in ordinary disk files, SQLite is a popular choice as the database to back small to medium-sized websites.</p></li> <li><p><b>Stand-in For An Enterprise RDBMS.</b> SQLite is often used as a surrogate for an enterprise RDBMS for demonstration purposes or for testing. SQLite is fast and requires no setup, which takes a lot of the hassle out of testing and which makes demos perky and easy to launch.</p></li> <li><p><a href="./whentouse.html">More suggestions...</a></p></li> </ul> |
Changes to pages/howtocompile.in.
︙ | ︙ | |||
18 19 20 21 22 23 24 | with the expectation that application developers can use these examples as guidance for developing their own custom compilation procedures. In other words, this article provides ideas and insights, not turnkey solutions.</p> <h2>Amalgamation Versus Individual Source Files</h2> | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | with the expectation that application developers can use these examples as guidance for developing their own custom compilation procedures. In other words, this article provides ideas and insights, not turnkey solutions.</p> <h2>Amalgamation Versus Individual Source Files</h2> <p>SQLite is built from over one hundred files of C code and script spread across multiple directories. The implementation of SQLite is pure ANSI-C, but many of the C-language source code files are either generated or transformed by auxiliary C programs and AWK, SED, and TCL scripts prior to being incorporated into the finished SQLite library. Building the necessary C programs and transforming and/or creating the C-language source code for SQLite is a complex process.</p> |
︙ | ︙ |
Changes to pages/index.in.
︙ | ︙ | |||
68 69 70 71 72 73 74 | </td> <td width="20"></td><td bgcolor="#044a64" width="1"></td><td width="20"></td> <td valign="top"> <h3>Current Status</h3> <p><ul> | | | > > > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | </td> <td width="20"></td><td bgcolor="#044a64" width="1"></td><td width="20"></td> <td valign="top"> <h3>Current Status</h3> <p><ul> <li><a href="releaselog/3_8_8_3.html">Version 3.8.8.3</a> of SQLite is recommended for all new development. Upgrading from version 3.8.8, 3.8.8.1, and 3.8.8.2 is optional. Upgrading from all other versions of SQLite is recommended.</li> </li> </ul></p> <h3>Common Links</h3> <p><ul> <li> <a href="features.html">Features</a> </li> <li> <a href="whentouse.html">When To Use SQLite</a> </li> <li> <a href="faq.html">Frequently Asked Questions</a> </li> <li> <a href="famous.html">Well-known Users</a> </li> <li> <a href="quickstart.html">Getting Started</a> </li> <li> <a href="lang.html">SQL Syntax</a> <ul> <li> <a href="pragma.html#toc">Pragmas</a> <li> <a href="lang_corefunc.html">SQL functions</a> |
︙ | ︙ |
Changes to pages/isolation.in.
︙ | ︙ | |||
91 92 93 94 95 96 97 | is flushed to disk and while all changes are still held in the writer's private memory space. But before any changes are made to the database file on disk, all readers must be (temporally) expelled in order to give the writer exclusive access to the database file. Hence, readers are prohibited from seeing incomplete transactions by virtue of being locked out of the database while the transaction is being written to disk. Only after the transaction is | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | is flushed to disk and while all changes are still held in the writer's private memory space. But before any changes are made to the database file on disk, all readers must be (temporally) expelled in order to give the writer exclusive access to the database file. Hence, readers are prohibited from seeing incomplete transactions by virtue of being locked out of the database while the transaction is being written to disk. Only after the transaction is completely written and synced to disk and commits are the readers allowed back into the database. Hence readers never get a chance to see partially written changes. </p> <p> WAL mode permits simultaneous readers and writers. It can do this because changes do not overwrite the original database file, but rather go |
︙ | ︙ |
Changes to pages/lang.in.
︙ | ︙ | |||
199 200 201 202 203 204 205 206 207 | "rename table" and "add column" commands shown above. However, applications can make other arbitrary changes to the format of a table using a simple sequence of operations. The steps to make arbitrary changes to the schema design of some table X are as follows: <ol> <li><p> Remember the format of all indexes and triggers associated with table X. | > > > > > > > | < < < < | < < < < < < < > > > > > > > > > > > > > | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | "rename table" and "add column" commands shown above. However, applications can make other arbitrary changes to the format of a table using a simple sequence of operations. The steps to make arbitrary changes to the schema design of some table X are as follows: <ol> <li><p> If foreign key constraints are enabled, disable them using [PRAGMA foreign_keys | PRAGMA foreign_keys=OFF]. <li><p> Start a transaction. <li><p> Remember the format of all indexes and triggers associated with table X. This information will be needed in step 8 below. One way to do this is to run a query like the following: SELECT type, sql FROM sqlite_master WHERE tbl_name='X'. <li><p> Use [CREATE TABLE] to construct a new table "new_X" that is in the desired revised format of table X. Make sure that the name "new_X" does not collide with any existing table name, of course. <li><p> Transfer content from X into new_X using a statement like: INSERT INTO new_X SELECT ... FROM X. <li><p> Drop the old table X: [DROP TABLE | DROP TABLE X]. <li><p> Change the name of new_X to X using: ALTER TABLE new_X RENAME TO X. <li><p> Use [CREATE INDEX] and [CREATE TRIGGER] to reconstruct indexes and triggers associated with table X. Perhaps use the old format of the triggers and indexes saved from step 3 above as a guide, making changes as appropriate for the alteration. <li><p>If any views refer to table X in a way that is affected by the schema change, then drop those views using [DROP VIEW] and recreate them with whatever changes are necessary to accommodate the schema change using [CREATE VIEW]. <li><p> If foreign key constraints were originally enabled then run [PRAGMA foreign_key_check] to verify that the schema change did not break any foreign key constraints. <li><p> Commit the transaction started in step 2. <li><p> If foreign keys constraints were originally enabled, reenable them now. </ol> <p>The procedure above is completely general and will work even if the schema change causes the information stored in the table to change. So the full procedure above is appropriate for dropping a column, changing the order of columns, adding or removing a UNIQUE constraint or PRIMARY KEY, adding CHECK or FOREIGN KEY or NOT NULL constraints, or changing the datatype for a column, for example. However, a simpler and faster procedure can optionally be used for some changes that do no affect the on-disk content in any way. The following simpler procedure is appropriate for removing CHECK or FOREIGN KEY or NOT NULL constraints, renaming columns, or adding or removing or changing default values on a column. <ol> <lI><p> Start a transaction. <li><p> Run [PRAGMA schema_version] to determine the current schema version number. This number will be needed for step 6 below. <li><p> Activate schema editing using [PRAGMA writable_schema | PRAGMA writable_schema=ON]. <li><p> Run an [UPDATE] statement to change the definition of table X in the [sqlite_master table]: UPDATE sqlite_master SET sql=... WHERE type='table' AND name='X'; |
︙ | ︙ | |||
294 295 296 297 298 299 300 | more than the old schema version number found in step 2 above. <li><p> Disable schema editing using [PRAGMA writable_schema | PRAGMA writable_schema=OFF]. <li><p> (Optional) Run [PRAGMA integrity_check] to verify that the schema changes did not damage the database. | < < | < > | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | more than the old schema version number found in step 2 above. <li><p> Disable schema editing using [PRAGMA writable_schema | PRAGMA writable_schema=OFF]. <li><p> (Optional) Run [PRAGMA integrity_check] to verify that the schema changes did not damage the database. <li><p> Commit the transaction started on step 1 above. </ol> <p>If some future version of SQLite adds new ALTER TABLE capabilities, those capabilities will very likely use one of the two procedures outlined above. <tcl> # One of the reasons that # SQLite does not currently support more ALTER TABLE capabilities is that |
︙ | ︙ | |||
559 560 561 562 563 564 565 | errors that can cause an automatic rollback include:</p> <ul> <li> [SQLITE_FULL]: database or disk full <li> [SQLITE_IOERR]: disk I/O error <li> [SQLITE_BUSY]: database in use by another process <li> [SQLITE_NOMEM]: out or memory | < < | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | errors that can cause an automatic rollback include:</p> <ul> <li> [SQLITE_FULL]: database or disk full <li> [SQLITE_IOERR]: disk I/O error <li> [SQLITE_BUSY]: database in use by another process <li> [SQLITE_NOMEM]: out or memory </ul>)^ <p> ^For all of these errors, SQLite attempts to undo just the one statement it was working on and leave changes from prior statements within the same transaction intact and continue with the transaction. ^However, depending on the statement being evaluated and the point at which the |
︙ | ︙ |
Changes to pages/news.in.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | hd_puts "<h3>$date - $title</h3>" regsub -all "\n( *\n)+" $text "</p>\n\n<p>" txt regsub -all {[Tt]icket #(\d+)} $txt \ {<a href="http://www.sqlite.org/cvstrac/tktview?tn=\1">\0</a>} txt hd_resolve "<blockquote>$txt</blockquote>" hd_puts "<hr width=\"50%\">" } newsitem {2015-01-30} {Release 3.8.8.2} { <p>The 3.8.8.2 patch release fixes a single minor problem: It ensures that the [sqlite3_wal_checkpoint(TRUNCATE)] operation will always truncate the [write-ahead log] even if log had already been reset and contained no new content. It is unclear if this is a bug fix or a new feature. | > > > > > > > > > > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | hd_puts "<h3>$date - $title</h3>" regsub -all "\n( *\n)+" $text "</p>\n\n<p>" txt regsub -all {[Tt]icket #(\d+)} $txt \ {<a href="http://www.sqlite.org/cvstrac/tktview?tn=\1">\0</a>} txt hd_resolve "<blockquote>$txt</blockquote>" hd_puts "<hr width=\"50%\">" } newsitem {2015-02-25} {Release 3.8.8.3} { <p>The 3.8.8.3 patch release fixes an obscure problem in the SQLite code generator that can cause incorrect results when the qualifying expression of a [partial index] is used inside the ON clause of a LEFT JOIN. This problem has been in the code since support for partial indexes was first added in version 3.8.0. However, it is difficult to imagine a valid reason to every put the qualifying constraint inside the ON clause of a LEFT JOIN, and so this issue has never come up before. <p>Any applications that is vulnerable to this bug would have encountered problems already. Hence, upgrading from the previous release is optional. } newsitem {2015-01-30} {Release 3.8.8.2} { <p>The 3.8.8.2 patch release fixes a single minor problem: It ensures that the [sqlite3_wal_checkpoint(TRUNCATE)] operation will always truncate the [write-ahead log] even if log had already been reset and contained no new content. It is unclear if this is a bug fix or a new feature. |
︙ | ︙ |
Changes to pages/queryplanner.in.
︙ | ︙ | |||
193 194 195 196 197 198 199 | </p> <h3>1.4 Multiple Result Rows</h3> <p> In the previous query the fruit='Peach' constraint narrowed the result down to a single row. But the same technique works even if multiple | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | </p> <h3>1.4 Multiple Result Rows</h3> <p> In the previous query the fruit='Peach' constraint narrowed the result down to a single row. But the same technique works even if multiple rows are obtained. Suppose we looked up the price of Oranges instead of Peaches: </p> <tcl> code {SELECT price FROM fruitsforsale WHERE fruit='Orange'} figure 6 #fig6 idx1lu2.gif {Indexed Lookup For The Price Of Oranges} </tcl> |
︙ | ︙ |
Changes to pages/tempfiles.in.
1 2 3 4 5 6 7 8 | <title>Temporary Files Used By SQLite</title> <tcl>hd_keywords {temporary disk files}</tcl> <h1 align="center">SQLite's Use Of Temporary Disk Files</h1> <h2>1.0 Introduction</h2> <p> | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <title>Temporary Files Used By SQLite</title> <tcl>hd_keywords {temporary disk files}</tcl> <h1 align="center">SQLite's Use Of Temporary Disk Files</h1> <h2>1.0 Introduction</h2> <p> One of the <a href="different.html">distinctive features</a> of SQLite is that a database consists of a single disk file. This simplifies the use of SQLite since moving or backing up a database is a simple as copying a single file. It also makes SQLite appropriate for use as an <a href="whentouse.html#appfileformat">application file format</a>. But while a complete database is held in a single disk file, SQLite does make use of many temporary files during the |
︙ | ︙ |
Changes to pages/whentouse.in.
1 2 | <title>Appropriate Uses For SQLite</title> | | | | | | < < < | > | < | > | > > > > > > > > > > > > > > > | > | < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < | < < < < < < < | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | <title>Appropriate Uses For SQLite</title> <h1 align="center">Appropriate Uses For SQLite</h1> <p> SQLite is not directly comparable to client/server SQL database engines such as MySQL, Oracle, PostgreSQL, or SQL Server since SQLite is trying to solve a different problem. </p> <p> Client/server SQL database engines strive to implement a shared repository of enterprise data. They emphasis scalability, concurrency, centralization, and control. SQLite strives to provide local data storage for individual applications and devices. SQLite emphasizes economy, efficiency, reliability, independence, and simplicity. </p> <p> SQLite does not compete with client/server databases. SQLite competes with [http://man.he.net/man3/fopen | fopen()]. </p> <h2>Situations Where SQLite Works Well</h2> <ul> <tcl>hd_fragment appfileformat</tcl> <li><b>Embedded devices and the internet of things</b> <p>Because an SQLite database requires no administration, it works well in devices that must operate without expert human support. SQLite is a good fit for use in cellphones, set-top boxes, televisions, game consoles, cameras, watches, kitchen appliances, thermostats, automobiles, machine tools, airplanes, remote sensors, drones, medical devices, and robots: the "internet of things". </p> <p>Client/server database engines are designed to live inside a lovingly-attended datacenter at the core of the network. SQLite works there too, but SQLite also thrives at the edge of the network, fending for itself while providing fast and reliable data services to applications that would otherwise have dodgy connectivity. </li> <li><p><b>Application file format</b></p> <p> SQLite is often used as the on-disk file format for desktop applications such as version control systems, financial analysis tools, media cataloging and editing suites, CAD packages, record keeping programs, and so forth. The traditional File/Open operation calls sqlite3_open() to attach to the database file. Updates happen automatically as application content is revised so the File/Save menu option becomes superfluous. The File/Save_As menu option can be implemented using the [backup API]. </p> <p>There are many benefits to this approach, including improved application performance, reduced cost and complexity, and improved reliability. See technical notes [file-format benefits|here] and [application file-format|here] for details. <li><p><b>Websites</b></p> <p>SQLite works great as the database engine for most low to medium traffic websites (which is to say, most websites). The amount of web traffic that SQLite can handle depends on how heavily the website uses its database. Generally speaking, any site that gets fewer than 100K hits/day should work fine with SQLite. The 100K hits/day figure is a conservative estimate, not a hard upper bound. SQLite has been demonstrated to work with 10 times that amount of traffic.</p> <p>The SQLite website ([https://www.sqlite.org/]) uses SQLite itself, of course, and as of this writing (2015) it handles about 400K to 500K HTTP requests per day, about 15-20% of which are dynamic pages touching the database. Each dynamic page does roughly 200 SQL statements. This setup runs on a single VM that shares a physical server with 23 others and yet still keeps the load average below 0.1 most of the time. </li> <li><p><b>Data analysis</b></p> <p> People who understand SQL can employ the [command-line shell|sqlite3 command-line shell] (or various third-party SQLite access programs) to analyze large datasets. Raw data can be imported from CSV files, then that data can be sliced and diced to generate a myriad of summary reports. More complex analysis can be done using simple scripts written in Tcl or Python (both of which come with SQLite built-in) or in R or other languages using readily available adaptors. Possible uses include website log analysis, sports statistics analysis, compilation of programming metrics, and analysis of experimental results. Many bioinformatics researchers use SQLite in this way. </p> <p> The same thing can be done with an enterprise client/server database, of course. The advantage of SQLite is that it is easier to install and use and the resulting database is a single file that can be written to a USB memory stick or emailed to a colleague. </p> </li> <li><p><b>Cache for enterprise data</b></p> <p> Many applications use SQLite as a cache of relevant content from an enterprise RDBMS. This reduces latency, since most queries now occur against the local cache and avoid a network round-trip. It also reduces the load on the network and on the central database server. And in many cases, it means that the client-side application can continue operating during network outages. </p> </li> <tcl>hd_fragment serversidedb {server-side database}</tcl> <li><p><b>Server-side database</b></p> <p> Systems designers report success using SQLite as a data store on server applications running in the datacenter, or in other words, using SQLite as the underlying storage engine for an application-specific database server.</p> <p>With this pattern, the overall system is still client/server: clients send requests to the server and get back replies over the network. But instead of sending generic SQL and getting back raw table content, the client requests and server responses are high-level and application-specific. The server translates requests into multiple SQL queries, gathers the results, does post-processing, filtering, and analysis, then constructs a high-level reply containing only the essential information.</p> <p>Developers report that SQLite is often faster than a client/server SQL database engine in this scenario. Database requests are serialized by the server, so concurrency is not an issue. Concurrency is also improved by "database sharding": using separate database files for different subdomains. For example, the server might have a separate SQLite database for each user, so that the server can handle hundreds or thousands of simultaneous connections, but each SQLite database is only used by one connection.</p> </li> <li><p><b>File archives</b></p> <p> The [https://www.sqlite.org/sqlar|SQLite Archiver] project shows how SQLite can be used as a substitute for ZIP archives or Tarballs. An archive of files stored in SQLite is only very slightly larger, and in some cases actually smaller, than the equivalent ZIP archive. And an SQLite archive features incremental and atomic updating and the ability to store much richer metadata. </p> <p>SQLite archives are useful as the distribution format for software or content updates that are broadcast to many clients. Variations on this idea are used, for example, to transmit TV programming guides to set-top boxes and to send over-the-air updates to vehicle navigation systems.</p> </li> <li><p><b>Replacement for <i>ad hoc</i> disk files</b></p> <p>Many programs use [http://man.he.net/man3/fopen | fopen()], [http://man.he.net/man3/fread | fread()], and |
︙ | ︙ | |||
142 143 144 145 146 147 148 | to try to code the same operations manually. Using an SQL database internally in this way also gives the program greater flexibility since new columns and indices can be added without having to recode every query. </p> </li> | < < < < < < < < < < < < < < < < < < < < < < | | < | | | < < < | | | | | | | | | | > | | < | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | to try to code the same operations manually. Using an SQL database internally in this way also gives the program greater flexibility since new columns and indices can be added without having to recode every query. </p> </li> <li><p><b>Stand-in for an enterprise database during demos or testing</b></p> <p> Client applications typically use a generic database interface that allows connections to various SQL database engines. It makes good sense to include SQLite in the mix of supported databases and to statically link the SQLite engine in with the client. That way the client program can be used standalone with an SQLite data file for testing or for demonstrations. </p> </li> <li><p><b>Education and Training</b></p> <p> Because it is simple to setup and use (installation is trivial: just copy the <b>sqlite3</b> or <b>sqlite3.exe</b> executable to the target machine and run it) SQLite makes a good database engine for use in teaching SQL. Students can easily create as many databases as they like and can email databases to the instructor for comments or grading. For more advanced students who are interested in studying how an RDBMS is implemented, the modular and well-commented and documented SQLite code can serve as a good basis. </p> </li> <li><p><b>Experimental SQL language extensions</b></p> <p>The simple, modular design of SQLite makes it a good platform for prototyping new, experimental database language features or ideas. </p> </li> </ul> <h2>Situations Where A Client/Server RDBMS May Work Better</h2> <ul> <li><p><b>Client/Server Applications</b><p> <p>If there are many client programs sending SQL to the same database over a network, then use a client/server database engine instead of SQLite. SQLite will work over a network filesystem, but because of the latency associated with most network filesystems, performance will not be great. Also, file locking logic is buggy many network filesystem implementations (on both Unix and Windows). If file locking does not work correctly, two or more clients might try to modify the same part of the same database at the same time, resulting in corruption. Because this problem results from bugs in the underlying filesystem implementation, there is nothing SQLite can do to prevent it.</p> <p>A good rule of thumb is to avoid using SQLite in situations where the same database will be accessed directly (without an intervening application server) and simultaneously from many computers over a network.</p> </li> <li><p><b>High-volume Websites</b></p> <p>SQLite will normally work fine as the database backend to a website. But if the website is write-intensive or is so busy that it requires multiple servers, then consider using an enterprise-class client/server database engine instead of SQLite.</p> </li> <li><p><b>Very large datasets</b></p> <p>An SQLite database is limited in size to 140 terabytes (2<sup><small>47</small></sup> bytes, 128 tibibytes). And even if it could handle larger databases, SQLite stores the entire database in a single disk file and many filesystems limit the maximum size of files to something less than this. So if you are contemplating databases of this magnitude, you would do well to consider using a client/server database engine that spreads its content across multiple disk files, and perhaps across multiple volumes. </p> </li> <li><p><b>High Concurrency</b></p> <p> SQLite supports an unlimited number of simultaneous readers, but it will only allow one writer at any instant in time. For many situations, this is not a problem. Writer queue up. Each application does its database work quickly and moves on, and no lock lasts for more than a few dozen milliseconds. But there are some applications that require more concurrency, and those applications may need to seek a different solution. </p> </li> </ul> <tcl> hd_fragment dbcklst {decision checklist} </tcl> <h2>Checklist For Choosing The Right Database Engine</h2> <ol> <li><p><b>Is the data separated from the application by a network? → choose client/server</b></p> <p>Relational database engines act as bandwidth-reducing data filters. So it is best to keep the database engine and the data on the same physical device so that the high-bandwidth engine-to-disk link does not have to traverse the network, only the lower-bandwidth application-to-engine link. <p>But SQLite is built into the application. So if the data is on a separate device from the application, it is required that the higher bandwidth engine-to-disk link be across the network. This works, but it is suboptimal. Hence, it is usually better to select a client/server database engine when the data is on a separate device from the application. <p><em>Nota Bene:</em> In this rule, "application" means the code that issues SQL statements. If the "application" is an [server-side database|application server] and if the content resides on the same physical machine as the application server, then SQLite might still be appropriate even though the end user is another network hop away.</p> </li> <li><p><b>Many concurrent writers? → choose client/server</b></p> <p>If many threads and/or processes need to write the database at the same instant (and they cannot queue up and take turns) then it is best to select a database engine that supports that capability, which always means a client/server database engine. <p>SQLite only supports one writer at a time per database file. But in most cases, a write transaction only takes milliseconds and so multiple writers can simply take turns. SQLite will handle more write concurrency that many people suspect. Nevertheless, client/server database systems, because they have a long-running server process at hand to coordinate access, can usually handle far more write concurrency than SQLite ever will. </li> <li><p><b>Big data? → choose client/server</b></p> <p>If your data will grow to a size that you are uncomfortable or unable to fit into a single disk file, then you should select a solution other than SQLite. SQLite supports databases up to 140 terabytes in size, assuming you can find a disk drive and filesystem that will support 140-terabyte files. Even so, when the size of the content looks like it might creep into the terabyte range, it would be good to consider a centralized client/server database. </li> <li><p><b>Otherwise → choose SQLite!</b></p> <p>For device-local storage with low writer concurrency and less than a terabyte of content, SQLite is almost always a better solution. SQLite is fast and reliable and it requires no configuration or maintenance. It keeps thing simple. SQLite "just works". </li> </ol> |