· 客户端/服务器程序
如果你有许多的客户端程序要通过网络访问一个共享的数据库, 你应当考虑用一个客户端/服务器数据库来替代SQLite. SQLite可以通过网络文件系统工作, 但是因为和大多数网络文件系统都存在延时, 因此执行效率不会很高. 此外大多数网络文件系统在实现文件逻辑锁的方面都存在着bug(包括Unix 和windows). 如果文件锁没有正常的工作, 就可能出现在同一时间两个或更多的客户端程序更改同一个数据库的同一部分, 从而导致数据库出错. 因为这些问题是文件系统执行的时候本质上存在的bug, 因此SQLite没有办法避免它们.
好的经验告诉我们, 应该避免在许多计算机需要通过一个网络文件系统同时访问同一个数据库的情况下使用SQLite.
· 高流量网站
SQLite通常情况下用作一个网站的后台数据库可以很好的工作. 但是如果你的网站的访问量大到你开始考虑采取分布式的数据库部署, 那么你应当毫不犹豫的考虑用一个企业级的客户端/服务器数据库来替代SQLite.
· 超大的数据集
当你在SQLite中开始一个事务处理的时候(事务处理会在任何写操作发生之前产生, 而不是必须要显示的调用BEGIN...COMMIT), 数据库引擎将不得不分配一小块脏页(文件缓冲页面)来帮助它自己管理回滚操作. 每1MB的数据库文件SQLite需要256字节. 对于小型的数据库这些空间不算什么, 但是当数据库增长到数十亿字节的时候, 缓冲页面的尺寸就会相当的大了. 如果你需要存储或修改几十GB的数据, 你应该考虑用其他的数据库引擎.
· 高并发访问
SQLite对于整个数据库文件进行读取/写入锁定. 这意味着如果任何进程读取了数据库中的某一部分, 其他所有进程都不能再对该数据库的任何部分进行写入操作. 同样的, 如果任何一个进程在对数据库进行写入操作, 其他所有进程都不能再读取该数据库的任何部分. 对于大多数情况这不算是什么问题. 在这些情况下每个程序使用数据库的时间都很短暂, 并且不会独占, 这样锁定至多会存在十几毫秒. 但是如果有些程序需要高并发, 那么这些程序就需要寻找其他的解决方案了.
4.5 H2 Database
h2是Thomas Mueller提供的一个开源的、纯java实现的关系数据库,官方网站:http://www.h2database.com/html/main.html。
它的主要特性是:
其他特性还包括
性能比较(摘自h2database网站)
Test Case |
Unit |
H2 |
HSQLDB |
Derby |
Simple: Init |
ms |
610 |
657 |
3187 |
Simple: Query (random) |
ms |
297 |
312 |
1828 |
Simple: Query (sequential) |
ms |
203 |
266 |
1766 |
Simple: Update (random) |
ms |
1078 |
1484 |
22031 |
Simple: Delete (sequential) |
ms |
234 |
281 |
7407 |
Simple: Memory Usage |
MB |
6 |
7 |
11 |
BenchA: Init |
ms |
859 |
438 |
4047 |
BenchA: Transactions |
ms |
5266 |
2875 |
17500 |
BenchA: Memory Usage |
MB |
9 |
14 |
10 |
BenchB: Init |
ms |
4016 |
2687 |
16875 |
BenchB: Transactions |
ms |
2609 |
3282 |
4250 |
BenchB: Memory Usage |
MB |
9 |
10 |
8 |
BenchC: Init |
ms |
891 |
594 |
5766 |
BenchC: Transactions |
ms |
4359 |
75438 |
11718 |
BenchC: Memory Usage |
MB |
9 |
18 |
9 |
Executed statements |
# |
594255 |
594255 |
594255 |
Total time |
ms |
20422 |
88314 |
96375 |
Statements per second |
# |
29098 |
6728 |
6166 |
包括Derby, HSQLDB等
方面 |
具体要求 |
必要条件 |
详细描述 |
License |
是否收费 |
|
免费使用 |
是否开源 |
|
开源 |
|
是否有技术支持 |
|
主要是社区支持,如果需要专业支持需要购买 |
|
商业目的的分发版本是否仍要收费 |
是 |
免费 |
|
其他 |
|
|
|
性能 |
数据容量支持100000条以上记录 |
是 |
支持 |
并发查询处理能力 |
|
SQLite在并发(包括多进程和多线程)读写方面的性能一直不太理想。数据库可能会被写操作独占,从而导致其它读写操作阻塞或出错。 |
|
查询速度 |
是 |
|
|
修改速度 |
是 |
|
|
平台支持 |
32/64位 |
|
全部支持 |
Linux/window/UNIX/mobile |
|
支持Linux/Mac OS/Windows |
|
运行方式支持 |
支持嵌入式 |
|
支持 |
支持独立运行 |
|
不支持 |
|
连接方式支持 |
支持ODBC |
|
默认不支持,必须通过第三方的ODBC驱动 |
支持JDBC |
|
默认不支持,必须通过第三方的JDBC驱动 |
|
支持内存访问 |
|
通过c接口(专用API) |
|
支持网络访问 |
|
不支持 |
|
SQL支持 |
支持SQL |
是 |
支持 |
支持Index,Trigger, Constrains,Views |
|
支持,有资料说其不支持外键约束。 |
|
管理界面 |
支持管理界面 |
|
支持CLI |
管理界面友好程度 |
|
较差 |
Altibase™内存数据库管理系统(DBMS),内存数据管理系统的最新技术,是一个在事务优先的环境中提供高性能和高可用性的软件解决方案。Altibase提供极限性能、容错能力和事务管理的方便性,特别是在通信、网上银行、证券交易、实时应用和嵌入式系统领域。Altibase能够最大限度的发挥数据库服务系统的潜力,使用Altibase能大大增强您公司的数据服务器的处理能力。
Altibase™内存DBMS为需要容错服务的系统提供实时数据库复制的功能。采用Altibase数据库复制的系统可以实现高性能、高可用性、数据库一致性、负载平衡和系统可伸缩性。如果您希望您的业务能够实现最大的成功,请在您的事务优先的系统中使用我们的Altibase数据库复制解决方案。
资料比较少,且需要商业License,没有详细去研究
Oracle是最重要的商业数据库产品提供商,它也有内存数据库的产品系列:主要就是Oracle Berkeley DB 和 Times Ten.前者是只支持嵌入式内存数据,后者是独立的内存优化数据库。
Oracle Berkeley DB是Oracle 收购了开源数据库厂商后推出的产品,其前身是Berkeley DB。它有开源版本,但且对于开源软件免费。商业版本是要付费。
Oracle Berkeley DB 系列的可嵌入开源数据库为开发人员提供了无需管理的快速、可靠的本地持久性。Oracle Berkeley DB 系列通常部署为“前沿”数据库,为不需要 SQL 的应用程序用例提供很高的性能、可靠性、可伸缩性以及可用性。
Oracle Berkeley DB 产品系列
— Berkeley DB — 事务处理式存储引擎,用于基本键/值数据结构中的非类型化数据 — 新增!版本 4.7 现已推出
— 针对 Java 环境优化的纯 Java 版 Berkeley DB — 新增!版本 3.3
— Berkeley DB XML — 原生 XML 数据库,可基于 XQuery 访问容器中存储的文档,并根据其内容进行索引 — 新增!版本 2.4 现已推出
Oracle 内存数据库 TimesTen 是一个针对内存进行了优化的关系数据库,它为应用程序提供了当今实时企业和行业(如电信、资本市场和国防)所需的即时响应性和非常高的吞吐量。Oracle 内存数据库 TimesTen 作为独立或嵌入式数据库部署在应用层中,利用标准的 SQL 接口对完全位于物理内存中的数据库进行操作。它也可以用作 Oracle 数据库的内存中数据库缓存,以改进用户应用程序的响应时间和吞吐量。
eXtremeDB内存式实时数据库是为实时系统及嵌入式系统而特别设计的数据库。与同类产品不同,eXtremeDB不是通过 对企业数据库面向实时嵌入式应用进行剪裁而来;而是总结了30年来McObject公司在编译器、实时编程、数据管理、内核级驱 动软件等领域的经验,面向实时嵌入式应用从头开发的最新实时数据管理技术。
eXtremeDB满足了您对实时数据库的一切期待:高级数据定义语言、并行访问、基于交易及灵活的索引… …等等。不仅如此,出乎您的意外,eXtremeDB在紧凑的引擎中还提供诸如事件触发、目标历史等等功能。
eXtremeDB嵌入式数据库满足更多的实时开发的要求。
· 最快的内存数据库。
· 极小尺寸和极小的内存消耗
· 多种索引支持
· 高可用性-组合选项
· 非常灵活的数据存储: 内存式,磁盘式或混合式
· 多种应用接口: 两种 SQL, 两种更快的原始接口
· 几乎牢不可破 -
又一个商业内存数据库产品,这个特点是实时数据库,号称最快。
(下接 4.5 H2 Database)
上述内存数据库,首先由于License限制,排除了所有的商业数据库产品包括:
Alitibase
Oralce Berkelay DB
Oracle TimesTen
eXtrmeDB
还包括 Berkelay DB这样的开源,但限制商业使用的数据库。
所以比较的重点就是SQLite和H2
方面 |
具体要求 |
必要条件 |
SQLite |
H2 |
License |
是否收费 |
|
免费使用 |
免费使用 |
是否开源 |
|
开源 |
开源 |
|
是否有技术支持 |
|
主要是社区支持,如果需要专业支持需要购买 |
主要是社区支持,如果需要专业支持需要购买 |
|
商业目的的分发版本是否仍要收费 |
是 |
免费 |
免费 |
|
其他 |
|
|
|
|
性能 |
数据容量支持100000条以上记录 |
是 |
支持 |
支持 |
并发查询处理能力 |
|
SQLite在并发(包括多进程和多线程)读写方面的性能一直不太理想。数据库可能会被写操作独占,从而导致其它读写操作阻塞或出错。 |
并发性较好(在模拟器中有使用,支持50个并发查询没问题) |
|
查询速度 |
是 |
|
数据量少的情况非常好 |
|
修改速度 |
是 |
|
|
|
平台支持 |
32/64位 |
|
全部支持 |
全部支持(需java平台支持) |
Linux/window/UNIX/mobile |
|
支持Linux/Mac OS/Windows |
全部支持(需java平台支持) |
|
运行方式支持 |
支持嵌入式 |
|
支持 |
支持 |
支持独立运行 |
|
不支持 |
支持 |
|
连接方式支持 |
支持ODBC |
|
不支持 |
支持 |
支持JDBC |
|
必须通过第三方的JDBC驱动 |
支持 |
|
支持内存访问 |
|
通过c接口(专用API) |
通过JDBC,不支持API访问 |
|
支持网络访问 |
|
不支持 |
支持 |
|
SQL支持 |
支持SQL |
是 |
支持 |
支持 |
支持Index,Trigger, Constrains,Views |
|
支持,有资料说其不支持外键约束。 |
支持 |
|
管理界面 |
支持管理界面 |
|
支持CLI |
支持Web界面的管理控制台 |
管理界面友好程度 |
|
较差 |
较好
|
下面分别对SQLite和H2进行了性能测试
主机: 操作系统: Windows XP;
CPU: Intel Dual 2.2GHZ;
内存: 1.99GB内存
测试目标版本:SQLite 3.6.12
测试数据库表ip_table结构如下
字段名 |
类型 |
Id(PK) |
Integer |
Dst_ip |
Varchar(20) |
Agent_ip |
Varchar(20) |
Dst_mac |
Varchar(20) |
Dst_port |
Integer |
Dst_vlan |
Varchar(20) |
|
|
使用C++编写了测试工程,启动测试程序后,先分别插入50000条和1000000条数据,然后执行一系列的测试
用例名 |
5w(条)单个线程 |
100w(条)单个线程 |
100w(条)10个并发线程 |
初始插入时间 |
2s |
45s |
|
初始插入时间(不加索引) |
1.782s |
38.109s |
|
插入1条记录 |
100纳秒以内 |
100纳秒以内 |
0.0016s |
插入1000条记录 |
0.047s |
0.047s |
0.453s |
插入1000条记录(无索引) |
0.6s |
1s |
11.39s |
查询一条记录 |
100纳秒以内 |
100纳秒以内 |
0.0033s |
查询一条记录(不使用索引) |
0.016s |
0.375s |
2.859s |
查询1000条记录 |
0.016s |
0.391s |
2.828s |
查询1000条记录(不使用索引) |
0.015s |
0.375s |
2.906s |
查询全部记录分组统计Group by |
0.688s |
15.473s |
|
查询1000 条(结果排序 ) |
0.031s |
0.39s |
2.453s |
查询所有记录(结果排序) |
0.766s |
16.203s |
33.594s |
更新一条记录 |
100纳秒以内 |
100纳秒以内 |
0.0043s |
更新一条记录(不使用索引) |
0.016s |
0.359s |
2.719s |
更新10000条数据 |
0.062s |
0.047s |
|
更新10000条数据(无索引) |
0.016s |
0.375s |
2.719s |
删除一条数据 |
100纳秒以内 |
100纳秒以内 |
0.0041s |
删除一条条数据(无索引) |
0.125s |
5.047s |
|
删除10000条数据 |
0.078s |
0.078s |
|
删除10000条数据(无索引) |
79-125ms |
5.031s |
|
结论:
1. SQLlite内存数据库的处理速度很快;
2. SQLlite内存数据库在查找数据时有索引的情况下,查询、更新、删除速度快;
3. SQLlite内存数据库并发性比较差,可以认为并发能力为0;
4. SQLlite内存数据库占用内存空间,100w条数据在40M左右(创建单个索引,6个字段)
5. 针对数据流探针来说,5w条数据SQLlite归并的速度在0.688s,可以尝试将部分功能用数据库归并实现。
6. SQLLite支持自定义函数,效率没有测试,应该和他提供的API效率差不多
7. SQLLite支持复合sql语句
主机: 操作系统: Windows Server 2003 Enterprise Edition SP2;
CPU: Intel Dual-Core 2.5GHz;
内存: 3.99GB内存
测试目标版本:H2database 1.1.110
测试数据库表employee结构如下
字段名 |
类型 |
ID(PK) |
Integer |
Name |
Varchar(20) |
Age |
Varchar(20) |
departmentID |
Varchar(20) |
测试数据库表department结构如下
字段名 |
类型 |
DeptID(PK) |
Integer |
Dept |
Varchar(20) |
mangerID |
Integer |
测试数据库表salary结构如下
字段名 |
类型 |
ID(PK) |
Integer |
F1 |
varchar(255) |
F2 |
varchar(255) |
F3 |
varchar(255) |
F4 |
varchar(255) |
F5 |
varchar(255) |
F6 |
varchar(255) |
F7 |
varchar(255) |
F8 |
varchar(255) |
F9 |
int |
使用Java编写了测试工程,启动测试程序后:
l 50000条级别的测试:先分别插入到employee表、department表、alary表中50000、和1000、50000条数据,然后执行一系列的测试
l 100w条级别的测试:先分别插入到employee表、department表、alary表中1000000、和1000、1000000条数据,然后执行一系列的测试
用例名 |
10w(条) |
100w(条) |
100w(条)10个并发线程 |
初始插入时间 |
5.43 |
50.47 |
|
初始插入内存 (KB) |
12376 |
12834 |
|
插入1条记录 |
0 |
0 |
|
插入5000条记录 |
0.4 |
0.39 |
2.95 |
查询1条记录(有索引) |
0 |
0 |
|
查询1条记录(无索引) |
0.71 |
6.95 |
|
查询5000条记录(有索引) |
0.015 |
0.1 |
0.7 |
查询1*5000条记录(有索引) |
|
0.23 |
1.26 |
查询5000条记录(无索引) |
0.73 |
7.2 |
|
查询全部记录 |
0.86 |
8.35 |
|
多表查询1条记录 |
0 |
0 |
|
多表查询5000条记录 |
0.016 |
0.016 |
|
更新1条记录(有索引) |
0 |
0 |
|
更新1条记录(无索引) |
0.45 |
4.62 |
|
更新5000条记录(有索引) |
0.16 |
0.18 |
2 |
更新1*5000条记录(有索引) |
|
0.15 |
1.7 |
更新5000条记录(无索引) |
0.62 |
5.1 |
|
删除1条记录(有索引) |
0 |
0 |
|
删除1条记录(无索引) |
0.68 |
6.6 |
|
删除5000条记录(有索引) |
0.1 |
0.12 |
1.1 |
删除1*5000条记录(有索引) |
|
0.13 |
0.9 |
删除5000条记录(无索引) |
0.77 |
6.95 |
|
嵌套查询(分组统计Group by) |
0.77 |
7.55 |
|
启动时间 |
0.11 |
0.2 |
|
测试结论:
优点:
1. 数据库小巧灵活;
2. 支持JDBC,对SQL支持良好,并支持内存模式;
3. 占用系统资源较少,启动较快;
4. 数据库支持并发访问;
5. 索引查询更新速度快;
缺点:
1. 大数量访问优势不明显,与常用数据库基本一致;
2. 无索引情况下速度较慢,与数据库的数据量成正比;
结论和建议
SQLite和H2内存数据库都比较快。
u 查询性能:查询一条记录 SQLite的性能要优于H2。查询(5000或10000)条 H2的性能要好于SQLite。
u 插入性能:性能差不多快,SQLite略快。
u 更新性能:更新一条记录 SQLite的性能好于H2。更新多条记录(有索引),SQLite【0.04s】的性能要好于H2【0.18s】
u 删除性能:删除一条记录.SQLite【非常小】的性能略好于H2【非常小】。删除多条记录,SQLite【0.078s】好于H2的【0.12s】
u 启动时间:都比较快
u 并发性能:H2的查询支持一定的并发性,要强于SQLite。更新和插入,基本上都没有并发可言。
总的看来,SQLite的性能要好于H2,但并发性不如。
另外SQLite一般使用C的API接口访问,而H2支持JDBC。
并且都可以大多数主流平台上
对于C/C++/C#应用而言,使用SQLite是更好的选择。对于Java应用,H2是不错的选择。
奇怪的两点:
1. 在无索引查询单条数据,SQLite的性能【0.375s】要比H2【6.9s】要快非常多。(原因发现是H2使用Big Long效率差了好多,比起Int)
2. 在无索引查询多条数据,SQLite的性能甚至比有索引时还好快一些????。而有索引情况下H2查询多条数据也好于SQLite