转载自:http://www.sqlite.com.cn/MysqLite/5/102.Html
sqlite 第三版总览
这篇文档简易的介绍了sqlite3.0版针对于2.8版的一些改进,适用于对sqlite2.8版比较了解的用户。
命名上的变化
在可预见的未来,错误修正这项功能将继续支持sqlite 2.8版。为了保证这两个版本可以共存,在3.0版本中,一些主要文件的名称和API的名称中都加了个”3“。例如,c程序内含文件的名称已经从"sqlite.h"改为"sqlite3.h".还有,用来和数据库一起操作的数据命令解释程序也 从"sqlite.exe" 改为 "sqlite3.exe"。有了这些命名上的区别,sqlite 2.8版和sqlite 3.0版就可以同时安装在同一个系统下了。另外,名称上的区别也使同一个C程序可以同时和2.8,3.0两个版本同时相连并使用同一个类库。
新的文件格式
sqlite的数据库文件格式已被完全更新, 2.1版的格式和3.0版的格式是互不兼容的。比如,2.8版的sqlite 是无法读取3.0版的sqlite数据库文件的,同样,3.0版的sqlite也是无法读取2.8版的 sqlite数据库文件的。
如想把sqlite 2.8版的数据库转换成3.0版的数据库的话,你可以用一些现成的命令行操作,比如输入下面的命令:
sqlite OLD.DB .dump | sqlite3 NEW.DB
新的数据库文件格式使用B+树型数据表格。在B+树中,所有的数据都被存储在(数据结构中)树结构端结点,而不是既在(数据结构中)树结构端结点又 在树的分支节点。B+树型数据表格具有很好的测量性,并且可以存储比较大的数据组。此外,传统的B-树也仍被应用在sqlite3.0的许多目录中。
新的文件格式可以存储的可变页的长度在512和32768字节之间。每页的文件长度都可以在页眉显示出来,所以从理论上来说,同一个类库可以读取不同长度的数据库,但实际上这一点还没有完全实现。
新的文件格式在磁盘映像中省略了没有被应用的区域。例如,目录仅仅显示B-树所存储的主要部分而不是显示所有的数据。也就是说,记录数据长度的区域 被省略了。整数值,比如说关键字的长度和关键数据可以用变长量来编译,这样一来,最常见的数据就可以只用一两个字节来显示了,还有,如果需要的话,最高 64字节的数据信息也是可以编译的。 在3.0版中,整数和浮动的点数据是用二进制来记录的,但在2.0版中,它们则是被转换成ASCII码的。所以,同一个数据库文件,如果是记录在 sqlite3.0中,就可以比记录在sqlite2.8中少占用25%至30%的磁盘空间。
关于 sqlite3.0版所采用的B-树的文件格式具体细节,你可以点击 btree.c 看标题注释。
弱类型和BLOB技术支持
sqlite2.8在数据库内部可以用不同的文件格式处理文件,但是,如果想把信息写到硬盘或是通过API和其它数据相连,所有文件格式都必须被转 换成ASCII文本格式。sqlite 3.0则不同,它可以把数据可内部的主要数据,也就是上文所提到的用变长量所表示的数据显示给用户,并在适当的时候用二进制的形式在磁盘中显示。为了支持 BLOB,非ASCII格式的数据也可以在磁盘中显示。
sqlite 2.8版有一个特点,就是任何类型的数据都可以存储在任意的数据列中,不受数据列所要求存储的文件类型的限制。这个特性被保留在3.0版中并有所改进。虽 然数据文件的格式决定了文件的类型,每列所存储的文件都要有规定的属性,但在3.0中每个列都是可以存储不同类型的数据的。当数据被存入一个数据列的时 候,这个列将尽全力把存入的数据的文件格式转换成该列所要求的文件格式。所有的sql数据库引擎都是这样的。所不同的是,sqlite 3.0 将存储数据即使转换该数据的文件类型是不可能的。
例如,一个数据列要求所存储的文件的类型是 "INTEGER",你输入一个字符串,这个列将自动检查所输入的字符串是否是数字,如果它确实看起来像是数字,字符串将被转换成数字,然后,如果这个数 字没有分数部分的话,它将被转换成整数存储起来。但是如果这个字符串不是一个规则的数字的话,它将仍被保存为一个字符串。如果一个列要求所存储的文件的类 型是"TEXT"的话,在存储数据之前,列将尝试把数字转换成 ASCII-Text来表示数据。但是,BLOBS在文本列仍然被保存成BLOBS,因为在通常情况下你是不可能把BLOB转换成文本的。
在大部分的其他的sql数据库引擎中,数据类型是和他该数据所处列的类型紧密相连的,但在sqlite3.0中,一个数据的类型只和自身有关,和所属列所要求的数据类型没有任何关联。 Paul Graham 在他的 ANSI Common Lisp 一书中称这个特性"manifest typing"为"弱类型". 其他的作者对"manifest typing"有不同的定义,我们不要混淆,不管它的名称是什么,我们知道它是3.0 的一个特性就好。
关于sqlite3.0版的数据类型的更多内容,点击separately.
支持UTF-8和UTF-16
在sqlite 3.0中,API中的程序可以识别UTF-8和UTF-16文本,并不改变主机中原来字节的顺序。每个数据库文件都可以用UTF-8,UTF-16BE (big-endian)和 UTF-16LE (little-endian)两种方式处理文本。在磁盘文件的内部,到处可见到同样的文本显示。如果数据库文件中所记载的文本显示(在文件标题中)和接 口程序所要求的文本显示不相符合的话,文本将被转换成当前所要求的文本格式。经常转换文本格式对于程序来说是非常麻烦的,所以建议程序员在一个应用程序中 自始至终使用一种文本格式。
当前,在执行sqlite的时候,sql的语法只能识别UTF-8文本,所以如果是UTF-16文本的话将被转换成UTF-8文本。当然这只是程序执行的问题,在不远的将来,更新版本的sqlite将完全有实力识别用sql所编译的UTF-16文本。
当开发用户所定义的sql函数和分类排序功能的时候,不管是UTF-8,UTF-16be或是 UTF-16le 文本格式,每个函数和分类排序都能清晰的识别文件。程序所执行的每一步都被完整无误的记录下来以便编译。当sql函数或分类排序要求相应的格式,但当前版 本的文件编译又无能为力的时候,文本将自动被转换。像以前一样,这种转换需要一定的时间,所以建议程序员挑选一种编码并自始至终使用以避免不必要的文本格 式转换。
不只是对于一个完整的文本,即使是某个文本中的格式不规则的字符串和格式不规则的UTF-8和UTF-16文本行,sqlite也要竭尽全力把他们 编译成规则的文件格式。所以如果你想存储IS08859数据的话,你可以使用UTF-8接口程序。只要不使用UTF-16分类排序或sql函数,文本的字 节顺序将不会被变更。
用户定义的分类排序
所谓的分类排序是指文本的排列顺序。当sqlite 3.0分类的时候(比如使用比较操作符"<" or ">="),它是按照数据类型分类的。
当比较两个文本行的时候使用分类排序。分类排序不改变空行,数字和BLOBS的顺序,它只改变文本的顺序。
分类排序功能是作为一个函数来执行的,它使用两个字符串来表示, 如果第一个字符串小于第二个字符串,则显示为负数, 如等于则显示为零,如大于则显示为正数。 sqlite 3.0版设置了一个名叫BINARY的独立的内置分类排序功能, 它是依靠标准C类库中的memcmp()程序来实现的。 BINARY分类排序功能很好的支持英文文档。对于其他语言或者在其他场合,程序会根据需要来选择合适的分类排序功能。
使用哪种分类排序是由sql中的COLLATE语句来决定的。一个COLLATE语句可分辨一种表格,它可以定义并默认表格中的每列该使用哪种分类 排序,目录的每个区段该使用哪种分类排序,或SELECTED语句中ORDER BY 字句该使用哪种分类排序。按照计划,sqlite还将使用标准的CAST()句法来具体定义每个分类排序。
64字节的行编号
表格中的每一行都有行标识符。如果表格中的某一列被定义为整数初级键控,那么那一列就成为其所属行的别名。但不管有没有定义这样一个列, 每个行都是有行编号的。
在sqlite 3.0版中,行编号是64字节的带符号整数。而在sqlite2.8中,行编号是32字节的。
为了占有最小的存储空间,64字节的行编号被存储为变长量。行编号在0和127之间的都只占有一个字节的空间。行编号在128和16383之间的只 占用2个字节的空间。 行编号在16383和2097152之间的占有三个字节的空间。依此类推。也可以使用负行编号, 担负行编号通常要占用9个字节的空间, 所以建议不要使用。sqlite所自动生成的行编号通常不是负行编号。
改良的并发性
sqlite 2.8允许多个进程同时读取或一个进程读取,但不允许读取和写入同时进行。sqlite 3.0则允许一个进程写入和其它多个进程同时读取。为了确认所更新的数据,输入者必须为数据库中的简短区间设置一个额外的锁,但这个锁不再像以前那样必须 贯穿在整个输入过程中。可以点击找到关于sqlite3.0 版中的锁的具体信息。
sqlite中也有一个在格式上有局限性的表格极的锁. 如果每个表格都存储了不同类型的文件,这些文件可以被连接到主数据库(使用ATTACH命令),这个被整合在一起的数据库依然可以作为一个整体来运行。但 各个文件将按照需要生成各自的锁。所以如果你把“数据库”重新定义成两个或更多数据库文件,那么在同一个数据库中同时对两个进程写入则是完全可能的。为了 更好的支持这项功能,同时处理两个或更多的ATTACHed型数据库是最基本的了。