本文部分转至http://www.cnblogs.com/hustcat/archive/2010/01/27/1657821.html
简介:
SQLite,是一款轻型的数据库,是遵守ACID的关系式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 C、C++、Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至今已经有12个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
SQLite包含在一个相对小的C库中。它是D.RichardHipp创建的公有领域项目。
不像常见的客户端/服务器结构范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
特性:
特点
简单(simple):SQLite是一个非常轻量级自包含(lightweight and self-contained)的DBMS:一个头文件,一个动态库文件,你就拥有了关系数据库的所有功能了。简单,是SQLite最明显的哲学。它提供的API少而简单。只需要一个DLL文件,你的程序马上就拥有了一个功能强大的数据库引擎,这是一件很美妙的事。
小巧(small):我用VS 2005在Windows下编译的3.6.11,Release版为368K,用时不到20秒——而编译MySQL时,要花上几分钟。而当我插入10000条int数据时,内存开销660K,磁盘开销92K。
事务(transaction):事务是现代商业数据处理系统最基本的要求,而Access,不论是在可执行文件大小(看了一下Access2003的可执行文件大小为6.32M,两者不是一个量级),还是事务特性,都是不能和SQLite 相比的。
并发性(Concurrency):由于SQLite通过OS的文件锁来实现库级锁,粒度很大,但是,它通过一些复杂特殊的处理(具体可以参见分析系列),尽量的提升了读写的并发度。如果你还有担心,你可以看看这篇文章:http://www.dbanotes.net/database/sqlite_cms.html。
SQL92:SQLite支持绝大部分的标准SQL语句,你只需要几百K的空间,就可以换来需要上百兆的通用DBMS几乎所有操作了。
方便(Convenience):如果你的程序要使用SQLite,只需要将拷贝你的程序目录即可。
开源(Opensource):这是它最强大的地方。开源,意味着你可以品读它的源码,你可以随时修改它,加入你自己的特性,而这一切完全免费的。开源,是一种精神。
实现部分
好了,现在从实现的角度来谈谈个人体会,这也是我比较关注的。
SQLite是一款优秀的嵌入式数据库管理系统,这里有两层含义:一是它经常作为动态库嵌入到应用程序;另外一方面它通常用于嵌入式设备或其它要求较低的桌面应用。如果把它作为内存数据库,个人觉得不是很适合。毕竟,它的写并发性不是很好,此时, TimesTen也许会更好,Berkey DB也许是一个不错的选择。SQLite这样的嵌入式数据库与主存数据库的应用场景、实现以及对资源的需求都是不一样的。
(1)事务处理
事务的核心问题有两个:并发控制和恢复。解决了并发控制和恢复问题的系统,就能允许它的用户假设程序是原子的(atomically)执行的——好像没有其它的程序同时执行;而且是可靠的(reliably)——不会产生失败。原子性和可靠性的抽象,则称为事务(transaction)。其实,事务并不是DBMS的专利,任何分布式系统,都面对并发和恢复问题,而解决的方法就是事务,只不过,我们更常听到DBMS中的事务。
并发控制保证事务的原子执行,它使得交错执行的事务看起来是一个接一个的顺序执行的,完全没有交错执行。如果交错执行的结果与顺序执行的结果一致,则称为串行化(serializable)。
恢复使得数据库仅仅包含那些正常完成的事务的结果。如果事务在执行的过程中发生错误,不能继续进行,恢复算法必须清除部分完成事务产生的影响。
- 并发控制
SQLite只支持库级锁,库级锁意味着什么?——意味着同时只能允许一个写操作,也就是说,即事务T1在A表插入一条数据,事务T2在B表中插入一条数据,这两个操作不能同时进行,即使你的机器有100个CPU,也无法同时进行,而只能顺序进行。表级都不能并行,更别说元组级了——这就是库级锁。但是,SQLite尽量延迟申请X锁,直到数据块真正写盘时才申请X锁,这是非常巧妙而有效的。
- 恢复
SQLite的恢复技术是影子分页技术(shadow paging)技术的典型代表。
DBMS的常用恢复技术有影子分页技术与基于日志的技术,前者在早其数据库管理系统中用到,比如System R,现代DBMS中已经很难见到它的身影了。
影子分页技术与基于日志技术相比,优点是实现简单,消除了写日志记录的开销,恢复的速度也快(不需要redo和undo)。影子分页的缺点就是事务提交时要输出多个块,这使得提交的开销很大,而且以块为单位,很难应用到允许多个事务并发执行的情况——这是它致命的缺点。
(2)查询处理
SQLite的查询处理本质上就是一个SQL编译器和一个虚拟机。而实现这些功能只用了十多个文件,整个实现实现简单而有效,但是也存在一些问题。首先,SQLite字典数据很简单,实际上它的字典就一个表sqlite_mater,所有的信息都是通过对sqlite_master中SQL语句进行解析获取的,而解析一个SQL语句,都需要进行词法分析、语法分析、甚至虚拟机代码的生成。而这一过程是很需要时间的,而且,查询计划也没有重用。其次,查询优化还比较简单,特别是连接操作,只通过循环来做(MySQL也一样)。但是,仅仅数万代码,我们不能对它要求太苛求。
(3)存储模型
SQLite的文件物理上被划分成相同大小的块;逻辑上划分成一些B-Tree——每个表对应一个B-Tree。而没有像Oracle,或者InnoDB对数据块进行复杂的逻辑组织,这种按需分配数据块的做法必然影响磁盘的读写性能。不过,归根到底,还是源于它的应用场景。
(4)缓冲区管理
Buffer的管理对于DBMS,无疑是非常重要的,SQLite在其它方面做得比较简单,但是在缓冲区管理这一块,它还是做足了功夫。SQLite采用DBMS常用的LRU算法。更值得一提的是,在较新的版本中,SQLite采用和虚拟文件系统的类似的方式,实现了让默认缓冲区管理子系统可以很容易的切换成其它的缓冲区管理算法,这是非常灵活的。
(5)I/O
SQLite采用简单的阻塞I/O,较新的版本将异步I/O作为可选的扩展,但是,由于SQLite没有日志,所以,事务中ACID中的D,就无法保证,所以,如果你的数据很关键,请不要用SQLite的异步I/O。另一方面,实际上,很多嵌入式操作系统,比如Windows CE并不支持异步I/O(不过,这可以通过多线程加以解决)。
但是,这些“缺点”并不是SQLite的缺点,相对于通过DBMS,恰恰是它的优点,这样的实现简单,而且对资源的需求较低。对嵌入式设备、或者那些要求较低的应用,已经足够,足够就好。