分类:
2006-07-20 09:00:35
摘 要 深入分析、比较Berkeley DB和sQLite。Berkel ey DB和sQLite是源码开放的嵌入式数据库管理系统,无需安装,体积小巧,速度又很快;可以很方便地应用在掌上电脑、PDA、车载设备、移动电话等MySQL、SQL Server这些大中型数据库不可实现的嵌入式设备上。
关键词Berkeley DB SOL,ite 嵌入式数据库
1 嵌入式数据库
通常,我们采用数据库来实现对数据的存储、检索等功能。像MySQL这类基于C/S结构的关系型数据库系统,虽然代表着目前数据库应用的主流,却并不能满足所有应用场合的需要。很多的应用,仅仅利用到了这些数据库产品的基本特性而已。有时我们需要的可能只是一个简单的基于磁盘文件的数据库系统,这样就不必安装庞大的数据库服务器,以简化数据库应用程序的设计。在某些特殊应用场合,比如在嵌入式系统中,由于系统的硬件软件资源都有限,这些数据库产品就明显有一些臃肿,甚至是不可实现的。在这些情况下,嵌入式数据库的优势就特别明显了。
嵌入式数据库通常与操作系统和具体应用集成在一起,无须独立运行的数据库引擎,由程序直接调用相应的API去实现对数据的存取操作。更直白地讲,嵌入式数据库是一种具备了基本数据库特性的数据文件。嵌入式数据库与其它数据库产品的区别是,前者是程序驱动式,而后者是引擎响应式。嵌入式数据库的一个很重要的特点是它们的体积非常小,编译后的产品也不过几十KB,在一些移动设备上极具竞争力。
从目前嵌入式应用的发展趋势来看,嵌入式数据库的实现必须充分体现系统的可定制性,即系统选择的技术路线要面向具体的行业应用,因而研究源码开放的嵌入式数据库具有特殊意义。
2 Berkeley DB和SQLite
DBkeley DB是一款健壮的、高速的工业级开放源代码的嵌入式数据库管理系统。应用它,程序员只需要调用一些简单的API就可以完成对数据的访问和管理。
Berkeley DB的源代码有C和Java两种,函数库本身只有300KB左右,但却能够用来管理多达256TB的数据。Berkeley DB作为一种嵌入式数据库系统在许多方面有着独特的优势。首先,由于其应用程序和数据库管理系统运行在相同的进程空间当中,进行数据操作时可以避免繁琐的进程间通信,因此耗费在通信上的开销自然也就降低到了极低程度。其次,Berkeley DB使用简单的函数调用接口来完成所有的数据库操作,而不是在数据库系统中经常用到的SQL语言,避免了对结构化查询语言进行解析和处理所需的开销。
SQLite的源代码是C,其源代码完全开放。SQLite第一个Alpha版本诞生于2000年5月。今年5月,SQLite又迎来了一个新的里程一SOLite 3。
SQLite有以下特性:支持ACID事务;零配置一无需安装和管理配置;储存在单一磁盘文件中的一个完整的数据库;数据库文件可以在不同字节顺序的机器间自由共享;支持数据库大小至2TB;足够小,全部源码大致3万行c代码,250KB;比目前流行的大多数数据库对数据的操作要快;提供了对事务功能和并发处理的支持,应用Transaction既保证了数据的完整性,也会提高运行速度,因为多条语句一起提交给数据库的速度会比一条一条的提交方式更快;独立,没有额外依赖。
目前,对Berkeley DB的研究开发工作主要是美国的sleepycat公司在进行,在国内几乎没有关于这方面的研究;而SQLite在国内也是鲜有人问津。
2.1 Berkeley DB和SOLite的数据库操作
与常用的数据库管理系统(如MySQL和Oracle等)有所不同,在Berkeley DB中并没有数据库服务器的概念。应用程序不需要事先同数据库服务建立起网络连接,而是通过内嵌在程序中的Berkeley DB函数库来完成对数据的保存、查询、修改和删除等操作。所有与数据库相关的操作都由函数库负责统一完成,这样无论是系统中的多个进程,或者是相同进程中的多个线程,都可以在同一时间调用访问数据库的函数;而底层的数据加锁、事务日志和存储管理等都在Berkeley DB函数库中实现。它们对应用程序来讲是完全透明的。
Berkeley DB不是关系型的数据库,不能应用标准的SQL语句对数据库操作,对它的操作要调用专用的API实现。这些API提供了查询、插入、删除等功能。比如com.sleepycat.db.Db类代表数据库对象。Db类的put( )方法完成的是插入功能;get( )方法完成的是读出数据的功能;com.sleepycat.db.Dbc是Berkeley DB的游标类,提供了遍历数据库记录的功能。
使用Berkeley DB提供的函数来进行数据库的访问和管理并不复杂。在大多数场合下,只需按照统一的接口标准进行调用就可以完成最基本的操作,Berkeley DBEnvironment为一组数据库同时提供参数设置。更为重要的是,如果要应用更高级的特性,必须要使用Environment功能,比如在要对保存的数据进行加密存储、利用其Transaction、数据加密、同步加锁控制、错误日志等功能的时候。
SQLite的SQL语言很大程度上实现了ANSI SQL92标准,特别是支持视图、触发器、事务,支持嵌套SQL。它通过SQL编译器(SQL Complier)来实现SQL语言对数据库进行操作,支持大部分的SQL命令,如attach database、begin transaction、comment、commit transaction、copy、create index、create table、create trigger、create view、delete、detach database、drop index、drop table、drop trigger、drop view、end transaction、explain、expression、insert、On conflict clause、pragma、replace、rollback transaction、select、update。
当然,也有一部分SQL命令SQLite并不支持。比如:不支持:Exists,虽然支持in(in是Exists的一种情况);不支持多数据库,如create table dbl.tablel as select*from db2.table 1;:不支持存储过程;不支持Alter View/Trigger/Table:不支持Truncate, 在SQLite中Delete不带Where字句时和Truancate的效果是一样的;不支持Floor和Ceiling函数,还有其它许多的函数;没有Auto Increment(自增)字段,但其实SQLite是支持Auto Increment的,即在将该字段设置为“INTEGER PRIMARY KEY”的时候;不支持If Exists等。
2.2 Berkeley DB和S0Lite与普通数据库的差别
Berkeley DB引入了一些新的基本概念,使得数据库应用程序访问和管理数据库变得相对简单起来。
(1)关键字和数据
关键字(key)和数据(data)是。Berkeley.DB用来进行数据库管理的基础,由这两者构成的key/data对,组成了数据库中的一个基本结构单元。整个数据库实际上就是由许多这样的结构单元构成的。通过使用这种方式,在通过API函数访问数据库时,只需提供关键字就能够访问到相应的数据。
关键字和数据在Berkeley DB中都是用一个名为DBT的简单结构来表示的。实际上两者都可以是任意长度的二进制数据。DBT的作用主要是保存相应的内存地址及其长度,其结构如下所示:
typedef struct {
void*data;
u_int32_t size;
u_int32_t ulen;
u_int32_f dlen;
u_int32_f doff;
u_int32_f flags;
}DBT;
在使用Berkeley DB进行数据管理时,缺省情况下是一个关键字对应于一个数据;但也可以将数据库配置成一个关键字对应于多个数据,而键值和数据必须是类com.sleepycat.db.Dbt的对象或其子类的对象。
(2)对象句柄
在Berkeley DB函数库定义的大多数函数都遵循同样的调用原则:首先创建某个结构,然后再调用该结构中的某些方法。从程序设计的角度来讲,这一点同面向对象的设计原则是非常类似的,即先创建某个对象的一个实例,然后再调用该实例的某些方法。正因为如此,.Berkeley DB引入了对象句柄的概念来表示实例化后的结构,并且将结构中的成员函数称为该句柄的方法。对象句柄的引入使得程序员能够凭借面向对象的思想,来完成对Berkeley DB数据库的访问和操作。
(3)错误处理
对于任何一个函数库来说,如何对错误进行统一的处理都是需要考虑的问题。Berkeley DB提供的所有函数都遵循同样的错误处理原则,即函数成功执行后返回零,否则返回非零值。
对于系统错误(如磁盘空间不足),返回的是一个标准的值;而对于非系统错误,返回的则是一个特定的错误编码。例如,如果在数据库中没有与某个特定关键字所对应的数据,那么在通过该关键字检索数据时就会出现错误。此时函数的返回值将是DB―NOTF0uND,表示在数据库中并没有所请求的关键字。所有标准的e rrn0值都大于零,而由Berkeley DB定义的特殊错误编码则都小于零。
Berkeley。DB提供了相应的函数来获得错误代号所对应的错误描述。一旦有错误发生,只需首先调用db_strerror( )函数来获得错误描述信息,然后再调用DB一>err()或DB->errx()就可以很轻松地输出格式化后的错误信息。
而SQLite最大的特点在于其数据类型为无数据类型(typelessness)。这意味着可以保存任何类型的数据到所想要保存的任何表的任何列中,无论这列声明的数据类型是什么。虽然在生成表结构的时候,要声明每个域的数据类型,但sQLite并不做任何检查。开发人员要靠自己的程序控制输入与读出数据的类型。这里有一个例外,就是当主键为整型值时,如果要插入一个非整型值时会产生异常。
诚然,SQLite允许忽略数据类型,但是,仍然建议在Create Table语句中指定数据类型,因为数据类型有利于增强程序的可读性。SQLite支持常见的数据类型,如VARCHAR、NVARCHAR、TEXT、INTEGER、FLOAT、BOOLEAN、CLOB、BLOB、TIMESTAMP、NUMERIC、VARYING、CHARACTER、NATl0NAI, VARYINGCHARACTER。
另外,虽然在插入或读出数据的时候是不区分类型的,但在比较的时候,不同数据类型是有区别的。比如:CREATE TABLE MyTable (a INTEGER,b TEXT);
INSERT INT0 MyTable VALIUES(0,0);
当执行查询
SELECT count(*)FROM MyTable WHERE a==’00’;时,会返回一条记录。因为字段a的类型是整型,而数字00与0是相等的。而执行查询
SELECT count(*)FROM MyTable WHERE b==‘00’:时,则不会返回记录。因为字段b是字符类型,字符“00”与“0”是不相等的。
2.3 Betkeley DB和SQLite数据存储方式比较
Berkeley DB对任何存入的数据都是按原样直接存储到数据文件中去,无论其是二进制数据还是A S C I I或Unicode等编码的文本。Berkeley DB提供了四种存储数据的模式:Btree、Hash、Queue和Recno。在打开数据库的时候,要指定一种存储模式。比如,上例中open( )方法中的参数Db.DB_BTREE就是指定以Btree模式打开数据库。
SQLite只提供了Btree存储数据的模式。对二进制数据,SQLite不能直接保存,但可以先将二进制的数据转换成ASCII编码,然后再保存。Base64.编码机制是最常见的把二进制数据转换成ASCII编码的手段。在SQLite的C语言代码encode.c中,提供了Base64编码的功能。
Btree模式是以排序的二叉树的方式存储的,Hash是以线性哈希表的方式存储。Queue用逻辑记录号作为键值,以定长的数据为记录值。Recno方式也以逻辑记录号作为键值,但可以保存定长或变长的记录值。这里提到的逻辑记录号有两种,即可变的和固定的。可变逻辑记录号会根据数据记录的增加与删除作相应的变化。Queue模式下,逻辑记录号只能是固定方式。Recno模式则可通过配置来选择是采用哪种类型的记录号作为键值。Btree模式也可以通过设置,将可变的逻辑记录号作为键值。
这几种存储模式各有优缺点,当键值不想用逻辑记录号时,Btree或Hash是必须的选择。Btree方式比较适合连续的顺序读取。比如,当键值是时间值,如果经常有从某一时间点开始连续读取后继的记录的操作,Btree是一种很好的选择。对随机的跳跃式读取,Hash模式则更为恰当。Queue和Recno都以记录号为键值,但前者适合先进先出的读取方式。Recno则通常是存取变长文本记录的理想存储模式。
2.4 Berkeley DB和S0Lite适用的系统
Berkeley DB为许多编程语言提供了实用的API接口,包括C、C++、Java、:Perl、Tcl、Python和PHP等。它适用平台UNIX/POSIX systems、win32以及嵌入式操作系统WinCE、VxWorks等。
通过Wrapper,SQLite实现了与其它语言的连接。所谓Wrapper即对SQLite提供的接口进行封装,使其它语言可以访问,使用SQLite。SQLite本身提供C和Tcl的接口,世界各地的程序员还提供了各种语言的SQLite的接口封装, 如Python、C++、Java、.Net等几乎所有流行的语言基本都有。sQLite提供一个抽象的操作系统接口层,来保证其在POSIX 与 Win32系统之间的兼容性。
2.5 其它方面
Berkeley DB没有数据库服务器的概念,使用简单的函数调用接口来完成所有的数据库操作,不使用SQL语言;接口简明实用,避免了对结构化查询语言进行解析和处理所需的开销,提高了执行速度;速度极快,可靠性高,但学习起来有一定难度。SQLite则简单易用,速度也很快,但功能却较Berkeley略有逊色,比如加密功能、二进制数据的处理等。
Berkeley DB虽然是开源的产品,但对某些条件下的商业性应用,却不是免费的,而且价格颇为昂贵。这些商业条件包括排除了开源的情况,不发放分布版本的情况等。SQLite是源代码完全的开放,可以免费用于任何用途,包括商业目的。
结语
随着人们对移动数据处理和管理需求的不断提高,与各种智能设备紧密结合的嵌入式数据库技术已经得到了学术界、工业界、民用部门等各方面的广泛重视。嵌入式数据库将会使得人们希望随时随地存取任意思数据信息的愿望成为现实,嵌入式数据库将无处不在。开源的嵌入式数据库Berkeley DB和SQLite,内核微小,有能够充分适应硬件的能力,能很好地适应嵌入式系统的需要。在具体的嵌入式应用中可以根据具体情况选择应用。