简单分析SQLite4的一些设计改变

(编辑:jimmy 日期: 2024/12/23 浏览:2)

1.0 内容提要

    SQLite4 是一个放在库中的紧凑的,自包含的,零维护的的ACID数据库引擎, 像SQLite3一样, 但具有改进的接口和文件格式.

    运行时环境封装到了一个对象之中.

    使用了一个很不错的键值对存储引擎:

  •         一个独立的大型键空间 - 不是SQLite3中那种每个表单独的键空间和索引.
  •         按字典顺序的键排序.
  •         多个存储引擎,可在运行时互换.
  •         默认在磁盘上的存储殷勤使用了一个日志结构的合并数据库.

    表的PRIMARY KEY真正被用作存储引擎的键.

    可以使用小数点运算.

    外键约束和递归触发器默认是启用的.

    覆盖指数可以显示声明.


2.0 概述

SQLite4 对于SQLite3而言,是一个可选方案,而不是一个替代方案. SQLite3 还没有过时. SQLite3 和 QLite4 将会并行受到支持. SQLite3 遗留的好处不会被抛弃.   SQLite3 还将会被持续的维护和改进. 但如果需要的话,新系统的设计者现在将可以选择 SQLite4 而不是 SQLite3.

SQLite4 努力保持了SQLite3的最优秀特性,同时在不破坏兼容性的前提下解决了SQLite3中无法修复的问题. SQLite3 和 SQLite4 中将会持续保持一样的特性有:

  •     SQLite4 是放在一个库中并链接到一个大型应用程序的完整的,关系型,事务性的, ACID, SQL 数据库引擎.  没有服务器,I/O直接面向硬盘.
  •     SQLite4 的源代码任何人可以用于任何目的.  没有版权、发布或者公开源代码或者编译二进制文件方面的的限制.  不用去担心烦人的许可证.
  •     使用了动态类型,而不是大多数其它的SQL数据库引擎所使用的僵化的静态类型.
  •     (默认)在磁盘上的镜像是一个单独的使用良好且稳定文件格式的磁盘文件, 使得SQLite4库适合于作为一个应用程序的文件格式使用.
  •     SQLite4 将会是快速且可靠的,无需管理员操心它就能运作的蛮好.
  •     SQLite4 的实现只有最简化的依赖,因而它可以很容易的集成到嵌入式系统或者其它非常规的运行时环境.

实现上仍然采用常用的汇编语言C。与SQLite3相比,SQLite4使用了更多C99特性,不过仍然可以使用常见的编译器编译。SQLite4使用了诸如size_t,int64_t,uint64_t以及其他标准数据类型。

SQLite4的编程接口与SQLite3的非常相似,只不过命名前缀都从sqlite3_更改为sqlite4_。SQLite3中旧的和作废的接口已经从SQLite4中剔除了。给一些函数增加了参数,有时对参数稍作修改或者对其参数顺序进行重新排序。修改了某些接口名字,使其更加符合其功能。总体上来说,SQLite4的编程接口与SQLite3的非常相似,这样移植一个SQLite3上的应用到SQLite4上只需花一个小时或者两个小时完成搜索替代就可以了。

SQLite3和SQLite4没有共用任何符号,因此把SQLite3和SQLite4同时嵌入到同一进程,同时使用它们都是可行的.

3.0 SQLite4的主要改变
3.1 运行时对象

SQLite4中一些接口的第一个参数接收一个(新加的)指向一个sqlite4_env对象的指针,它定义了运行时环境。需要接收sqlite4_env指针的示例程序包括:

  •     sqlite4_open()
  •     sqlite4_malloc(), sqlite4_realloc(), and     sqlite4_free()
  •     sqlite4_mprintf()
  •     sqlite4_random()
  •     sqlite4_config()

一个sqlite4_env对象实例定义了SQLite4与其他系统交互是如何交互的。一个sqlite4_env对象包含的方法能够:

  •     分配,进入,离开和收回互斥体
  •     分配,调整和释放堆内存,
  •     访问和控制底层键/值存储引擎,
  •     使用高质量随机种子初始化内建PRNG,
  •     取得当前时间和日期与本地时区,
  •     记录error日志消息.


标准平台(windows和Unix)的SQLite4构建包含了一个全局sqlite4_env对象,通常这个对象适配于所在平台。如果一个接口程序的参数中有一个指向sqlite4_env对象的指针,而且传给这个参数的指针是空指针时,这个接口程序就会使用默认的全局sqlite4_env对象。另外,某些应用可能要求在相同的地址空间上运行两个或者多个SQLite4实例,同时每个实例使用了各自不同的互斥原语,不同的内存堆以及不同的时间日期函数等等。SQLite4通过对每个数据库实例创建不同的sqlite4_env对象来满足这种需求。sqlite4_env对象中还废除了全局和静态变量,这样就可以非常容易地把SQLite4移植到哪些对静态或者全局数据提供有限支持的嵌入式系统中。

3.2 简化的键/值存储引擎

相对于SQLite3,SQLite4使用的键/值存储引擎拥有一个大大简化了的接口。这个存储引擎是可拔插的;通过对qlite4_env对象在打开新的数据库连接前做适当的改动,它可以在运行时被改变。

SQLite4 需要一个实现了有序键/值对的存储引擎,它的键和值是任意长度的二进制数据。键必须惟一,且按字典排序。也就是说,键应该根据一个比较函数进行排序,例如:
 复制代码 代码如下:
int key_compare(const void *key1, int n1, const void *key2, int n2){
  int c = memcmp(key1, key2, n1<n2 "htmlcode">

CREATE INDEX cover1 ON table1(a,b) COVERING(c,d);

上面的 cover1 索引可以在存储引擎中用一个单一的查找操作来进行形式如 "SELECT c,d FROM table1 WHERE a=" 的查询.  索引中如果没有附加的 COVERING 子句, SQLite4 也许会在存储引擎中做两次操作; 一次操作基于a和b的值来找到主键,而第二次操作则基于主键来找到c和d的值. COVERING 子句使得c和d的值在索引中就可用,这意味着它们无需第二次查找就可以从索引中提取出来.


COVERING 语句上有一个变化:
 

CREATE INDEX cover2 ON table(x,y) COVERING ALL;

COVERING ALL 语句的意思是数据表的所有列都在索引中被重复一份,这就确保了原来的数据表永远也不会被访问到,以完成一个使用了这个索引的查询.  这种方法的缺点,当然就是信息重复,而且因此让数据库文件更大.  但是通过在索引指标上明确指定COVERING关闭,SQLite4可以让应用程序开发者权衡着从应用程序中腾出空间和时间来让其更加适用.