SQLite是遵守ACID的轻型数据库引擎,它包含在一个相对较小的C库中。它是D.RichardHipp创建的公有领域项目。不像常见的客户端/服务器结构范例,SQLite引擎不是一个与程序通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。其简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
一、特性
(1)支持原子的、一致的、独立和持久 (ACID) 的事务,即使在系统崩溃或电源断电后也能保持数据完整性。
(2)零配置 – 无需安装和管理配置。
(3)实现多数SQL92标准(但不是全部)。对SQL92标准的支持包括ACID事务、索引、约束、触发和查看等。不支持外键约束,授权和收回权限等。
(4)一个完整的数据库存储在单一的跨平台的文件中。
(5)支持2TB大小的数据库和GB级大小的字符串和二进制对象。
(6)足够小,到3.7.14版忽略掉注释大约6.5万行代码。
(7)对大部分普通的数据库操作,比很多流行的客户/服务器模式的数据库都要快。
(8)简单、易使用的API。
(9)使用ANSI-C编写。支持大多数语言的绑定,如C++, PHP, Python, Perl, Java, C#, Tcl, Rails, Delphi, COM/VB DLL, Objective-C等等,还有ODBC接口。
(10)良好注释的源代码,并且有着100%的测试覆盖率。
(11)所有源代码包含在一个单一的ANSI-C源文件中,很容易嵌入到项目中。
(12)自包含:没有外部依赖。
(13)跨平台:支持Unix(Linux, Mac OS-X, Android, iOS),Windows(Win32, WinCE, WinRT),也很容易移植到其他系统上。
(14)源代码属于公有领域,可用于任何用途,包括商业应用。
(15)附带一个管理SQLite数据库的命令行工具。
SQLite的数据库权限只依赖于文件系统,没有用户帐户的概念。SQLite有数据库级锁定,没有网络服务器,并且可以实现多数SQL92标准(但不是全部)。SQL92标准的其他一些主要功能是外键和检查限制。SQLite通过数据库级上的独占性和共享锁定来实现独立事务处理。这意味着多个进程和线程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据。在某个进程或线程向数据库执行写入操作之前,必须获得独占锁定。在发出独占锁定后,其他的读或写操作将不会再发生。
SQLite的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源率非常低,在嵌入式设备中,可能只需几百K的内存就足够。目前SQLite被广泛地用于多个产品,包括Adobe Photoshop, Airbus, Dropbox, Firefox, Thunderbird, Flame, Google的很多项目,McAfree,Microsoft的游戏项目,PHP语言,Python语言,Skype,Toshiba的很多项目,等等。
SQLite还非常健壮,其创建者保守地估计SQLite可以处理每天负担多达10000次点击率的Web站点,并且SQLite有时候可以处理10倍于上述数字的负载。
二、数据类型
SQLite是无类型(Typelessness)的,这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中,无论这列声明的数据类型是什么,对于SQLite来说对字段不指定类型是完全有效的(只有在一种情况下不是,即在字段类型为”Integer Primary Key”时)。如:
Create Table ex1(a, b, c);
实际上SQLite不支持静态数据类型,而是使用列关系。这意味着它的数据类型不具有表列属性,而具有数据本身的属性。当某个值插入数据库时,SQLite将检查它的类型。如果该类型与关联的列不匹配,则SQLite会尝试将该值转换成列类型。如果不能转换,则该值将作为其本身具有的类型存储。
诚然SQLite允许忽略数据类型,但是仍然建议在你的Create Table语句中指定数据类型。因为数据类型对于你和其他的程序员交流,或者你准备换掉你的数据库引擎时能起到一个提示或帮助的作用。 SQLite支持常见的数据类型,包括NULL、INTEGER、REAL、TEXT和BLOB数据类型。如:
CREATE TABLE ex2(
a VARCHAR(10),
b NVARCHAR(15),
c TEXT,
d INTEGER,
e FLOAT,
f BOOLEAN,
g CLOB,
h BLOB,
i TIMESTAMP,
j NUMERIC(10,5)
k VARYING CHARACTER (24),
l NATIONAL VARYING CHARACTER(16)
);
三、功能
SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库,它支持的SQL包括:
aggregate functions: avg(X), count(X), count(*), group_concat(X), group_concat(X,Y), max(X), min(X), sum(X), total(X).ALTER TABLE
ANALYZE
ATTACH DATABASEBEGIN TRANSACTION
commentCOMMIT TRANSACTION
core functions: abs(X), changes(), coalesce(X,Y,...), glob(X,Y), ifnull(X,Y), hex(X), last_insert_rowid(), length(X), like(X,Y), like(X,Y,Z), load_extension(X), load_extension(X,Y), lower(X), ltrim(X), ltrim(X,Y), max(X,Y,...), min(X,Y,...), nullif(X,Y), quote(X), random(), randomblob(N), replace(X,Y,Z), round(X), round(X,Y), rtrim(X), rtrim(X,Y), soundex(X), sqlite_compileoption_get(N), sqlite_compileoption_used(X), sqlite_source_id(), sqlite_version(), substr(X,Y,Z), substr(X,Y), total_changes(), trim(X), trim(X,Y), typeof(X), upper(X), zeroblob(N).CREATE INDEXCREATE TABLECREATE TRIGGERCREATE VIEWCREATE VIRTUAL TABLE
date and time functions: date(), time(), datetime(), julianday(), strftime().DELETE
DETACH DATABASEDROP INDEXDROP TABLEDROP TRIGGERDROP VIEWEND TRANSACTION
EXPLAIN
expression
INDEXED BY INSERT
keywordsON CONFLICT clause
PRAGMA
REINDEX
RELEASE SAVEPOINTREPLACEROLLBACK TRANSACTION
SAVEPOINTSELECTUPDATE
VACUUM
同时它还支持事务处理功能等等。某种程度上SQLite有点像Microsoft的Access,都是文件型数据库,一个数据库就是一个文件,在这个文件中可建立多张表,可以建立索引、触发器等。备份这个文件就备份了整个数据库。但是,SQLite支持跨平台,操作简单,能够使用很多语言直接创建数据库,而不像Access需要Office的支持。
四、管理SQLite
SQLite附带一个命令行管理工具。通过数据库名称可以调用此命令行程序,并且可以按照下面的方式创建新的数据库和表:
C:\Users\Kim>sqlite3 alf.db
SQLite version <%版本号%> 2016-08-28 20:11:36
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
sqlite> create table mytable(name varchar(40), age smallint);
sqlite> insert into mytable values('Jack-Zhou', 23);
sqlite> select * from mytable;
Jack-Zhou|23
sqlite> .tables
mytable
sqlite> .schema CREATE TABLE mytable(name varchar(40), age smallint);
sqlite>
上面创建一个alf数据库,在其中创建一个表mytable,插入一条数据;而后列出数据库中的所有表和模式。
SQLite还附带一个命令行数据库分析器,该分析器允许您显示关于任何SQLite数据库当前状态的详细信息:
C:\Users\Kim>sqlite3_analyzer alf.db /** Disk-Space Utilization Report For alf.db
Page size in bytes.................... 1024
Pages in the whole file (measured).... 2
Pages in the whole file (calculated).. 2
Pages that store data................. 2 100.0%
Pages on the freelist (per header).... 0 0.0%
Pages on the freelist (calculated).... 0 0.0%
Pages of auto-vacuum overhead......... 0 0.0%
Number of tables in the database...... 2
Number of indices..................... 0
Number of named indices............... 0
Automatically generated indices....... 0
Size of the file in bytes............. 2048
Bytes of user payload stored.......... 13 0.63%
*** Page counts for all tables with their indices ********************
MYTABLE............................... 1 50.0%
SQLITE_MASTER......................... 1 50.0%
*** All tables *******************************************************
Percentage of total database.......... 100.0%
Number of entries..................... 2
Bytes of storage consumed............. 2048
Bytes of payload...................... 91 4.4%
Average payload per entry............. 45.50
Average unused bytes per entry........ 916.50
Fragmentation......................... 0.0%
Maximum payload per entry............. 78
Entries that use overflow............. 0 0.0%
Primary pages used.................... 2
Overflow pages used................... 0
Total pages used...................... 2
Unused bytes on primary pages......... 1833 89.5%
Unused bytes on overflow pages........ 0
Unused bytes on all pages............. 1833 89.5%
*** Table MYTABLE ****************************************************
Percentage of total database.......... 50.0%
Number of entries..................... 1
Bytes of storage consumed............. 1024
Bytes of payload...................... 13 1.3%
Average payload per entry............. 13.00
Average unused bytes per entry........ 999.00
Maximum payload per entry............. 13
Entries that use overflow............. 0 0.0%
Primary pages used.................... 1
Overflow pages used................... 0
Total pages used...................... 1
Unused bytes on primary pages......... 999 97.6%
Unused bytes on overflow pages........ 0
Unused bytes on all pages............. 999 97.6%
由于完全能够使用命令行界面来管理数据库,因此它可以为数据库管理员带来很大的方便。当然还有许多优秀的第三方SQLite管理工具,如基于QT的SQLiteMan,Firefox插件SQLite Manager,SQLiteSpy等等。
另外,备份SQLite数据库有两种方法。如果数据库没有处于使用状态,则可以直接将数据库文件复制到安全位置;如果数据库正在使用中,则应从命令行界面使用.dump命令(.dump命令也可以用于备份数据库表),创建一个包含必要命令和数据的文件,从而重新创建数据库:
C:\Users\Kim>sqlite3 alf.db
SQLite version 3.7.14 2012-09-03 15:42:36
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .dump
PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE mytable(name varchar(40), age smallint); INSERT INTO "mytable" VALUES('Jack-Zhou',23); COMMIT;
sqlite>
五、不支持的SQL特性
相对于试图列出SQLite支持的所有SQL92特性,只列出不支持的部分要简单得多。下面列出的就是SQLite所不支持的SQL92特性(按列表的顺序关系,接近列表顶部的特性更可能在不远的将来加入):
(1)RIGHT OUTER JOIN和FULL OUTER JOIN:已经实现了LEFT OUTER JOIN,但还没实现RIGHT OUTER JOIN和FULL OUTER JOIN。
(2)完整的ALTER TABLE支持:只支持ALTER TABLE命令的RENAME TABLE和ADD COLUMN操作。 其他ALTER TABLE操作如DROP COLUMN、ALTER COLUMN、ADD CONSTRAINT等等均被忽略。
(3)完整的触发器支持:支持FOR EACH ROW触发器,但不支持FOR EACH STATEMENT触发器。
(4)可写视图:SQLite中的视图是只读的。你不可以在视图上执行DELETE、INSERT或UPDATE。但是你可以创建一个试图在视图上DELETE、INSERT、UPDATE时触发的触发器,然后在触发器中完成你所需要的工作。
(5)GRANT和REVOKE:由于SQLite读和写的是一个普通的磁盘文件,因此唯一可以获取的权限就是操作系统的标准文件访问权限。一般在客户机/服务器架构的关系型数据库系统上能找到的GRANT和REVOKE命令,但对于一个嵌入式数据库引擎来说是没有意义的,因此没有实现。
六、应用场合
SQLite不同于其他大部分的SQL数据库引擎,因为它的首要设计目标就是简单化:
* 易于管理
* 易于使用
* 易于嵌入其他大型程序
* 易于维护和配置
许多人喜欢SQLite就是因为它的小巧和快速。但是这些特性只是它的部分优点,使用者还会发现SQLite是非常稳定的。出色的稳定性源于它的简单,越简单就越不容易出错。除了上述的简单、小巧和稳定性外,最重要的在于SQLite力争做到简单化。
简单化在一个数据库引擎中可以说是一个优点,但也可能是个缺点,主要决定于你想要做什么。为了达到简单化,SQLite省略了一些人们认为比较有用的特性,例如高并发性、严格的存取控制、丰富的内置功能、存储过程、复杂的SQL语言特性、XML以及Java的扩展、超大的万亿级别的数据测量等等。如果你需要使用上述的这些特性并且不介意它们的复杂性,那么SQLite也许就不适合你了。SQLite没有打算作为一个企业级的数据库引擎,也并不打算和Oracle或者PostgreSQL竞争。
仅凭经验来说SQLite适用于以下场合:当你更看中简单的管理、使用和维护数据库,而不是那些企业级数据库提供的不计其数的复杂功能的时候,使用SQLite是一个比较明智的选择。事实也证明,人们在许多情况下已经清楚的认识到简单就是最好的选择。
SQLite最佳试用场合:
(1)应用程序文件格式
SQLite作为桌面应用程序的本地磁盘文件格式取得了巨大成功。例如金融分析工具、CAD包、档案管理程序等等。一般的数据库打开操作需要调用sqlite3_open()函数,并且标记一个显式本地事务的起始点(BEGIN TRANSACTION)来保证以独占的方式得到文件的内容。文件保存将执行一个提交(COMMIT)同时标记另一个显式本地事务起始点。这种事务处理的作用就是保证对于应用程序数据文件的更新是原子的、持久的、独立的和一致的。
数据库里可以加入一些临时的触发器,用来把所有的改变记录在一张临时的取消/重做日志表中。当用户按下取消/重做按钮的时候这些改变将可以被回滚。这项技术实现一个无限级的取消/重做功能只需要编写很少的代码。
(2)嵌入式设备和应用软件
因为SQLite数据库几乎不需要管理,因此对于那些无人值守运行或无人工技术支持的设备或服务,SQLite是一个很好的选择。SQLite能很好的适用于手机、PDA、机顶盒,以及其他仪器。作为一个嵌入式数据库它也能够很好的应用于客户端程序。
(3)网站
作为数据库引擎SQLite适用于中小规模流量的网站(也就是说99.9%的网站)。SQLite可以处理多少网站流量在于网站的数据库有多大的压力。通常来说,如果一个网站的点击率少于100000次/天的话,SQLite是可以正常运行的。100000次/天是一个保守的估计,不是一个准确的上限。事实证明,即使是10倍的上述流量的情况下SQLite依然可以正常运行。
(4)替代某些特别的文件格式
许多程序使用fopen()、fread()或fwrite()函数创建和管理一些自定义的文件用来保存数据。使用SQLite替代这些自定义的文件格式将是一种很好的选择。
(5)内部的或临时的数据库
对于那些有大量的数据需要用不同的方式筛选分类的程序,相对于编写同样功能的代码,如果你把数据读入一个内存中的SQLite数据库,然后使用连接查询和ORDER BY子句按一定的顺序和排列提取需要的数据,通常会更简单和快速。按照上述的方法使用内嵌的SQLite数据库将会使程序更富有灵活性,因为添加新的列或索引不用重写任何查询语句。
(6)命令行数据集分析工具
有经验的SQL用户可以使用SQLite命令行程序去分析各种混杂的数据集。原始数据可以从CSV文件(逗号分隔值文件)中导入,然后被切分产生无数的综合数据报告。可能的用法包括网站日志分析、运动统计分析、编辑规划标准、分析试验结果。
当然也可以用企业级的客户端/服务器数据库来做同样的事情。在这种情况下使用SQLite的好处是:SQLite的部署更为简单并且结果数据库是一个单独的文件,你可以把它存储在软盘或者优盘或者直接通过email发给同事。
(7)在Demo或测试版的时候作为企业级数据库的替代品
如果你正在编写一个使用企业级数据库引擎的客户端程序,使用一个允许你连接不同SQL数据库引擎的通用型数据库后台将是很有意义的。其更大的意义在于将SQLite数据库引擎静态的连接到客户端程序当中,从而内嵌SQLite作为混合的数据库支持。这样客户端程序就可以使用SQLite数据库文件做独立的测试或者验证。
(8)数据库教学
因为SQLite的安装和使用非常的简单(安装过程几乎忽略不计,只需要拷贝SQLite源代码或sqlite.exe可执行文件到目标主机,然后直接运行就可以),所以它非常适合用来讲解SQL语句。同学们可以非常简单地创建他们喜欢的数据库,然后通过电子邮件发给老师批注或打分。对于那些感兴趣怎样实现一个关系型数据库管理系统(RDBMS)的高层次的学生, 按照模块化设计且拥有很好的注释和文档的SQLite源代码,将为他们打下良好的基础。这并不是说SQLite就是如何实现其他数据库引擎的精确模型,但是很适合学生们了解SQLite是如何快速工作的,从而掌握其他数据库系统的设计实现原则。
(9)试验SQL语言的扩展
SQLite简单且模块化的设计使得它可以成为一个用来测试数据库语言特性或新想法的优秀的原型平台。
七、哪些场合适合使用其他的关系型数据库管理系统(RDBMS)
(1)客户端/服务器程序
如果你有许多的客户端程序要通过网络访问一个共享的数据库,你应当考虑用一个客户端/服务器数据库来替代SQLite。SQLite可以通过网络文件系统工作,但是因为和大多数网络文件系统都存在延时,因此执行效率不会很高。此外大多数网络文件系统在实现文件逻辑锁的方面都存在着bug(包括Unix和Windows)。如果文件锁没有正常的工作,就可能出现在同一时间两个或更多的客户端程序更改同一个数据库的同一部分,从而导致数据库出错。因为这些问题是文件系统执行的时候本质上存在的bug,因此SQLite没有办法避免它们。
好的经验告诉我们,应该避免在许多计算机需要通过一个网络文件系统同时访问同一个数据库的情况下使用SQLite。
(2)高流量网站
SQLite通常情况下用作一个网站的后台数据库可以很好的工作。但是如果你的网站的访问量大到你开始考虑采取分布式的数据库部署,那么你应当毫不犹豫的考虑用一个企业级的客户端/服务器数据库来替代SQLite。
(3)超大的数据集
当你在SQLite中开始一个事务处理的时候(事务处理会在任何写操作发生之前产生,而不是必须要显示的调用BEGIN...COMMIT),数据库引擎将不得不分配一小块脏页(文件缓冲页面)来帮助它自己管理回滚操作。每1MB的数据库文件SQLite需要256字节。对于小型的数据库这些空间不算什么,但是当数据库增长到数十亿字节的时候,缓冲页面的尺寸就会相当的大了。如果你需要存储或修改几十GB的数据,你应该考虑用其他的数据库引擎。
(4)高并发访问
SQLite对于整个数据库文件进行读取/写入锁定。这意味着如果任何进程读取了数据库中的某一部分,其他所有进程都不能再对该数据库的任何部分进行写入操作。同样的,如果任何一个进程在对数据库进行写入操作,其他所有进程都不能再读取该数据库的任何部分。对于大多数情况这不算是什么问题,在这些情况下每个程序使用数据库的时间都很短暂,并且不会独占,这样锁定至多会存在十几毫秒。但是如果有些程序需要高并发,那么这些程序就需要寻找其他的解决方案了。
作者:惜祯