给定一个探针键,SQLite4需要能够找到它最近的键,然后以字典序升序或降序遍历键。向一个已有的键插入数据时会覆盖旧数据。事务,包括原子提交和回滚,由存储引擎负责。
SQLite4经由表和索引,将所有数据存储到一个单独的键空间, 与此相反,SQLite3中每个表和索引都需要一个单独的键空间。SQLite4的存储也与SQLite3不同,因为它需要存储引擎以字典序对键进行排序, 而SQLite3使用了一个非常复杂的比较函数来决定记录的存储顺序。
SQLite4与存储引擎之间的通信是通过一个定义完善的并且简单的接口进行的。新的存储引擎可以在运行期间进行替换:只要在指定数据库连接之前替换sqlite4_env对象里的某些函数指针就可以了。
如果替换的存储引擎不支持回滚,那么这就意味着SQLite4无法运行ROLLBACK。如果替换的存储引擎不支持事务嵌套,那么这就意味着SQLite4无法运行嵌套事务。因此,嵌入到SQLite4中的存储引擎的功能越少,对应的整体的系统功能就会越差。
默认情况下内置的存储引擎是日志结构的合并式数据库。它比LevelDB要快很多倍,支持嵌套式事务,它把整个内容存储在单一的磁盘文件里。SQLite4的未来版本还可能包含一个内置的采用B树结构的存储引擎。
3.3 现在的PRIMARY KEY是真正的主键
Sqlite3允许声明表中的任何单个或多列为主键。但在内部,SQLite3只将PRIMARY KEY简单地当做唯一约束来对待。实际中用于存储使用的键是每一行的rowid。
Sqlite4则相反,它真实地使用声明的表主键(更确切地说是PRIMARY KEY的编码值)作为键而插入存储引擎。SQLite4表通常没有rowid(除非在表没有PRIMARY KEY的情况下,这时需要一个rowid作为隐式主键。)这意味着内容在磁盘中按主键的顺序存储。这也意味着可以通过对PRIMARY KEY的一次查询即可定位记录。在SQLite3中,主键上的一个搜索意味着在自动创建的索引中先找到rowid,然后依据该rowid对主表做一个二次搜索。
SQLite4 需要 PRIMARY KEY 的所有元素不能为空. 这是一条SQL标准. 由于早期版本的疏忽, SQLite3 没有在PRIMARY KEY 列上强制加上这条NOT NULL约束,到该漏洞被发现的时候SQLite3已经在被广泛使用了, NOT NULL 约束的激活就可能会对太多的程序造成影响. 3.4 十进制数
SQLite4 使用十进制算数做所有的数字计算. SQLite4 从不使用C类型的double或者float(除了在double和内部十进制表示之间转换时使用语接口例程中). 相反,所有数字值在内部表示方式为一个带有3位数字的基于10的指数的18位十进制数. 这一表示方式的特性有:
即使是在缺乏对于IEEE 754 binary64浮点数字支持的平台上,其运作起来也是可靠和兼容的. 货币计算通常可以精确的进行,不需要四舍五入. 任何有符号和无符号的64位整数都能被精确的表示. 浮点数范围和精确度超出了 IEEE 754 binary64 浮点数. 正无穷和负无穷以及 NaN (Not-a-Number) 都有良好的表示方式.SQLite4 使得整型和浮点型数字之间没有了差别. 不过期却有精确和近似数之间的分别. 在 C/C++ 中, 整形数是精确的而浮点数是近似的. 但SQLite4并不一定如此. 浮点数字在SQLite4可以是精确的. 可以用64位表示的整型数在SQLite4中总是精确的,而大型的整型数则可能是近似的.
SQLite4 数字格式是面向内部使用的. 数字可以在整型和double型之间转换,用于输入和输出. 磁盘上的存储空间需要从1到12位的SQLite4数字值, 这取决于其大小和重要的位数.
3.5 外键约束和递归触发器是默认开启的
外键约束在SQLite3的早期版本中是没有的,并且他们默认关闭了向后兼容的能力。但是外键约束一直是有效的,并且在SQLite4中是默认打开的。所有的外键约束都是默认延迟的,尽管他们能够被定义成立即创建。但是,没有有效的机制去触发外键约束,不管是延迟创建还是立即创建。
SQLite3提供了递归触发器,但是这只是在一个运行时才有效的功能。在SQLite4中,所有的触发器在所有的时间段里都是递归的。
3.6 明确的索引覆盖
SQLite4 像 CREATE TABLE 语句中条件了一个可选的子句,该子句定义了在索引中重复的附加列信息. 这可以让应用程序开发者在SQLite4中无需使用任何花招就可以明确地创建覆盖索引. 例如:
上面的 cover1 索引可以在存储引擎中用一个单一的查找操作来进行形式如 "SELECT c,d FROM table1 WHERE a=?1 AND b=?2" 的查询. 索引中如果没有附加的 COVERING 子句, SQLite4 也许会在存储引擎中做两次操作; 一次操作基于a和b的值来找到主键,而第二次操作则基于主键来找到c和d的值. COVERING 子句使得c和d的值在索引中就可用,这意味着它们无需第二次查找就可以从索引中提取出来.
COVERING 语句上有一个变化:
COVERING ALL 语句的意思是数据表的所有列都在索引中被重复一份,这就确保了原来的数据表永远也不会被访问到,以完成一个使用了这个索引的查询. 这种方法的缺点,当然就是信息重复,而且因此让数据库文件更大. 但是通过在索引指标上明确指定COVERING关闭,SQLite4可以让应用程序开发者权衡着从应用程序中腾出空间和时间来让其更加适用.