SQLite Database Speed Comparison
SQLite Database Speed Comparison
Database Speed Comparison
注意:这个文件非常古老。它描述了SQLite,MySQL和PostgreSQL的古老版本之间的速度比较。
这里的数字变得毫无意义。此页面仅作为历史文物保留。
Executive Summary
运行一系列测试来测量SQLite 2.7.6,PostgreSQL 7.1.3和MySQL 3.23.41的相对性能。以下是从这些实验中得出的一般结论:
- 对于大多数常见操作,SQLite 2.7.6比RedHat 7.2上的默认PostgreSQL 7.1.3安装速度快得多(有时高达10或20倍)。
- 对于大多数常见操作,SQLite 2.7.6通常比MySQL 3.23.41更快(有时是速度的两倍)。
- SQLite不像其他数据库那样快速地执行CREATE INDEX或DROP TABLE。但这并不是一个问题,因为这些并不常见。
- 如果将多个操作组合到一个事务中,SQLite的效果最佳。
这里给出的结果有以下警告:
- 这些测试并未尝试测量涉及多个连接和子查询的复杂查询的多用户性能或优化。
- 这些测试是在一个相对较小的(大约14兆字节)数据库上。他们并没有衡量数据库引擎如何适应更大的问题。
Test Environment
用于这些测试的平台是具有1GB或内存和IDE磁盘驱动器的1.6GHz Athlon。操作系统是带有库存内核的RedHat Linux 7.2。
所使用的PostgreSQL和MySQL服务器默认在RedHat 7.2上交付。(PostgreSQL版本7.1.3和MySQL版本3.23.41。)没有努力调整这些引擎。特别注意RedHat 7.2上的默认MySQL配置不支持事务。不必支持事务处理就可以给MySQL带来很大的速度优势,但SQLite仍然能够在大多数测试中保持自己的地位。
我被告知RedHat 7.3中默认的PostgreSQL配置不必要的保守(它可以在8MB内存的机器上运行),并且通过一些知识丰富的配置调整,PostgreSQL可以运行得更快。马特警长报告说,他已经调整了他的PostgreSQL安装并重新运行下面显示的测试。他的结果显示PostgreSQL和MySQL的运行速度大致相同。对于Matt的结果,请访问
SQLite的测试与它在网站上显示的配置相同。它使用-O6优化和-DNDEBUG = 1编译,禁用SQLite代码中的许多“assert()”语句。-DNDEBUG = 1编译器选项大致加倍SQLite的速度。
所有的测试都是在另一台静止的机器上进行的。一个简单的Tcl脚本被用来生成和运行所有的测试。这个Tcl脚本的副本可以在文件tools / speedtest.tcl
的SQLite源代码树中找到。
在所有测试中报告的时间表示以秒为单位的挂钟时间。SQLite报告了两个单独的时间值。第一个值是SQLite在默认配置下打开全磁盘同步。打开同步后,SQLite执行一个fsync()
系统调用(或等价)来确定关键数据实际上已写入磁盘驱动器表面。如果在数据库更新过程中操作系统崩溃或计算机意外关闭,则同步对于确保数据库的完整性是必要的。SQLite的第二次报告是关闭同步的时间。关闭同步功能后,SQLite有时会快得多,但操作系统崩溃或意外的电源故障可能会损坏数据库。一般来说,同步SQLite时间用于与PostgreSQL(也是同步的)进行比较,异步SQLite时间用于与异步MySQL引擎进行比较。
Test 1: 1000 INSERTs
CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100) INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three' INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty' ... 省略
了995行
PostgreSQL: | 4.373 |
---|---|
MySQL: | 0.114 |
SQLite 2.7.6: | 13.061 |
SQLite 2.7.6 (nosync): | 0.223 |
因为它没有一个中央服务器来协调访问,所以SQLite必须关闭并重新打开数据库文件,从而使每个事务的缓存失效。在此测试中,每条SQL语句都是一个单独的事务,因此必须打开和关闭数据库文件,并且缓存必须刷新1000次。尽管如此,SQLite的异步版本仍然和MySQL一样快。但是,注意同步版本的速度要慢很多。SQLite 在每次同步事务之后调用fsync()
,以确保所有数据在继续之前都安全地存储在磁盘表面上。在同步测试的13秒钟内,SQLite处于空闲状态,等待磁盘I / O完成。
Test 2: 25000 INSERTs in a transaction
BEGIN; CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100) INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two' ...
省略了24997行 IN
SERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine' INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six' COMMIT;
PostgreSQL: | 4.900 |
---|---|
MySQL: | 2.184 |
SQLite 2.7.6: | 0.914 |
SQLite 2.7.6 (nosync): | 0.757 |
当所有INSERT被放入事务中时,SQLite不再需要关闭并重新打开数据库,或者在每个语句之间使其缓存失效。它也不需要做任何fsync()直到最后。当以这种方式解决问题时,SQLite比PostgreSQL和MySQL要快得多。
Test 3: 25000 INSERTs into an indexed table
BEGIN; CREATE TABLE t3(a INTEGER, b INTEGER, c VARCHAR(100) CREATE INDEX i3 ON t3(c ...
省略了24998行 IN
SERT INTO t3 VALUES(24999,88509,'eighty eight thousand five hundred nine' INSERT INTO t3 VALUES(25000,84791,'eighty four thousand seven hundred ninety one' COMMIT;
PostgreSQL: | 8.175 |
---|---|
MySQL: | 3.197 |
SQLite 2.7.6: | 1.555 |
SQLite 2.7.6 (nosync): | 1.402 |
有报道说SQLite在索引表上的表现不佳。最近增加了这个测试来反驳这些谣言。确实,SQLite创建新索引条目的速度并不像其他引擎那样快(参见下面的测试6),但其总体速度仍然更好。
Test 4: 100 SELECTs without an index
BEGIN; SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<1000; SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<1100; ... 省略了96 行 SELECT count(*), avg(b) FROM t2 WHERE b>=9800 AND b<10800; SELECT count(*), avg(b) FROM t2 WHERE b>=9900 AND b<10900; COMMIT;
PostgreSQL: | 3.629 |
---|---|
MySQL: | 2.760 |
SQLite 2.7.6: | 2.494 |
SQLite 2.7.6 (nosync): | 2.526 |
此测试在没有索引的25000条目表上执行100个查询,因此需要全表扫描。在此测试中,以前的SQLite版本比PostgreSQL和MySQL要慢,但最近的性能增强已经提高了它的速度,因此它现在是该组中速度最快的。
Test 5: 100 SELECTs on a string comparison
BEGIN; SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one%'; SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%two%';
... 省略了96行
SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%ninety nine%'; SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one hundred%'; COMMIT;
PostgreSQL: | 13.409 |
---|---|
MySQL: | 4.640 |
SQLite 2.7.6: | 3.362 |
SQLite 2.7.6 (nosync): | 3.372 |
该测试仍然执行100次全表扫描,但它使用字符串比较而不是数字比较。SQLite的速度比PostgreSQL快三倍,比MySQL快大约30%。
Test 6: Creating an index
CREATE INDEX i2a ON t2(a CREATE INDEX i2b ON t2(b
PostgreSQL: | 0.381 |
---|---|
MySQL: | 0.318 |
SQLite 2.7.6: | 0.777 |
SQLite 2.7.6 (nosync): | 0.659 |
SQLite在创建新索引时速度较慢。这不是一个很大的问题(因为新的索引不是经常创建的),但它正在进行中。希望未来版本的SQLite在这里可以做得更好。
Test 7: 5000 SELECTs with an index
SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<100; SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<200; SELECT count(*), avg(b) FROM t2 WHERE b>=200 AND b<300; ... 省略了4994行 SELECT count(*), avg(b) FROM t2 WHERE b>=499700 AND b<499800; SELECT count(*), avg(b) FROM t2 WHERE b>=499800 AND b<499900; SELECT count(*), avg(b) FROM t2 WHERE b>=499900 AND b<500000;
PostgreSQL: | 4.614 |
---|---|
MySQL: | 1.270 |
SQLite 2.7.6: | 1.121 |
SQLite 2.7.6 (nosync): | 1.162 |
所有三个数据库引擎在运行索引时都会运行得更快。但SQLite仍然是最快的。
Test 8: 1000 UPDATEs without an index
BEGIN; UPDATE t1 SET b=b*2 WHERE a>=0 AND a<10; UPDATE t1 SET b=b*2 WHERE a>=10 AND a<20; ... 省略了996行 UPDATE t1 SET b=b*2 WHERE a>=9980 AND a<9990; UPDATE t1 SET b=b*2 WHERE a>=9990 AND a<10000; COMMIT;
PostgreSQL: | 1.739 |
---|---|
MySQL: | 8.410 |
SQLite 2.7.6: | 0.637 |
SQLite 2.7.6 (nosync): | 0.638 |
对于这个特定的UPDATE测试,MySQL一直比PostgreSQL和SQLite慢五到十倍。我不知道为什么。MySQL通常是一个非常快速的引擎。也许这个问题已经在更高版本的MySQL中解决了。
Test 9: 25000 UPDATEs with an index
BEGIN; UPDATE t2 SET b=468026 WHERE a=1; UPDATE t2 SET b=121928 WHERE a=2;
... 省略了24996 行
UPDATE t2 SET b=35065 WHERE a=24999; UPDATE t2 SET b=347393 WHERE a=25000; COMMIT;
PostgreSQL: | 18.797 |
---|---|
MySQL: | 8.134 |
SQLite 2.7.6: | 3.520 |
SQLite 2.7.6 (nosync): | 3.104 |
就在最近的2.7.0版本中,SQLite的运行速度与MySQL的测试速度大致相同。但是最近对SQLite的优化比UPDATE的速度提高了一倍多。
Test 10: 25000 text UPDATEs with an index
BEGIN; UPDATE t2 SET c='one hundred forty eight thousand three hundred eighty two' WHERE a=1; UPDATE t2 SET c='three hundred sixty six thousand five hundred two' WHERE a=2;
... 省略了24996行
UPDATE t2 SET c='three hundred eighty three thousand ninety nine' WHERE a=24999; UPDATE t2 SET c='two hundred fifty six thousand eight hundred thirty' WHERE a=25000; COMMIT;
PostgreSQL: | 48.133 |
---|---|
MySQL: | 6.982 |
SQLite 2.7.6: | 2.408 |
SQLite 2.7.6 (nosync): | 1.725 |
再次,SQLite 2.7.0版本的运行速度与MySQL相同。但是现在2.7.6版本的速度比MySQL快两倍,比PostgreSQL快了二十多倍。
公平对待PostgreSQL,它开始在这个测试中颠簸。知识渊博的管理员可以通过稍微调整和调整服务器来让PostgreSQL在这里运行得更快。
Test 11: INSERTs from a SELECT
BEGIN; INSERT INTO t1 SELECT b,a,c FROM t2; INSERT INTO t2 SELECT b,a,c FROM t1; COMMIT;
PostgreSQL: | 61.364 |
---|---|
MySQL: | 1.537 |
SQLite 2.7.6: | 2.787 |
SQLite 2.7.6 (nosync): | 1.599 |
在这个测试中,异步SQLite只比MySQL更慢。(MySQL似乎特别擅长INSERT ... SELECT语句。)PostgreSQL引擎依然在颠簸 - 它所使用的61秒中的大部分都花在等待磁盘I / O上。
Test 12: DELETE without an index
DELETE FROM t2 WHERE c LIKE '%fifty%';
PostgreSQL: | 1.509 |
---|---|
MySQL: | 0.975 |
SQLite 2.7.6: | 4.004 |
SQLite 2.7.6 (nosync): | 0.560 |
SQLite的同步版本是该测试中组最慢的,但异步版本是最快的。不同的是执行fsync()所需的额外时间。
Test 13: DELETE with an index
DELETE FROM t2 WHERE a>10 AND a<20000;
PostgreSQL: | 1.316 |
---|---|
MySQL: | 2.262 |
SQLite 2.7.6: | 2.068 |
SQLite 2.7.6 (nosync): | 0.752 |
这个测试很重要,因为它是PostgreSQL比MySQL更快的少数几个之一。然而,异步SQLite比其他两个更快。
Test 14: A big INSERT after a big DELETE
INSERT INTO t2 SELECT * FROM t1;
PostgreSQL: | 13.168 |
---|---|
MySQL: | 1.815 |
SQLite 2.7.6: | 3.210 |
SQLite 2.7.6 (nosync): | 1.485 |
一些旧版本的SQLite(2.4.0版之前)会在一系列删除操作后面显示新的INSERT后显示性能下降。正如本测试所示,问题现在已经解决。
Test 15: A big DELETE followed by many small INSERTs
BEGIN; DELETE FROM t1; INSERT INTO t1 VALUES(1,10719,'ten thousand seven hundred nineteen' ..
. 省略了11997 行
INSERT INTO t1 VALUES(11999,72836,'seventy two thousand eight hundred thirty six' INSERT INTO t1 VALUES(12000,64231,'sixty four thousand two hundred thirty one' COMMIT;
PostgreSQL: | 4.556 |
---|---|
MySQL: | 1.704 |
SQLite 2.7.6: | 0.618 |
SQLite 2.7.6 (nosync): | 0.406 |
SQLite非常擅长在事务中执行INSERT,这可能解释了为什么在此测试中它比其他数据库快得多。
Test 16: DROP TABLE
DROP TABLE t1; DROP TABLE t2; DROP TABLE t3;
PostgreSQL: | 0.135 |
---|---|
MySQL: | 0.015 |
SQLite 2.7.6: | 0.939 |
SQLite 2.7.6 (nosync): | 0.254 |
当涉及到删除表时,SQLite比其他数据库要慢。这可能是因为当SQLite删除一个表时,它必须通过并擦除数据库文件中与该表有关的记录。另一方面,MySQL和PostgreSQL使用单独的文件来表示每个表,以便他们可以简单地通过删除文件来删除表,这会更快。
另一方面,删除表不是一个非常常见的操作,所以如果SQLite需要更长的时间,这并不是一个大问题。
SQLite is in the Public Domain.