此处的数字已失去意义。此页面仅作为历史记录保留。
进行了一系列测试,以衡量 SQLite 2.7.6、PostgreSQL 7.1.3 和 MySQL 3.23.41 的相对性能。以下是从这些实验中得出的总体结论
对于大多数常见操作,SQLite 2.7.6 明显更快(有时快 10 或 20 倍),比 RedHat 7.2 上默认的 PostgreSQL 7.1.3 安装快。
对于大多数常见操作,SQLite 2.7.6 通常更快(有时快两倍以上),比 MySQL 3.23.41 快。
SQLite 执行 CREATE INDEX 或 DROP TABLE 的速度不如其他数据库快。但这并不是问题,因为这些操作并不频繁。
如果您将多个操作组合到单个事务中,SQLite 的效果最佳。
此处提供的结果带有以下注意事项
这些测试未尝试衡量多用户性能或涉及多个联接和子查询的复杂查询的优化。
这些测试是在一个相对较小的(大约 14 兆字节)数据库上进行的。它们没有衡量数据库引擎在更大问题上的扩展能力。
这些测试使用的平台是 1.6GHz Athlon,配备 1GB 内存和 IDE 磁盘驱动器。操作系统是 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 RAM 的机器上运行),并且可以通过一些专业的配置调整使 PostgreSQL 运行得更快。Matt Sergeant 报告说,他已经调整了他的 PostgreSQL 安装并重新运行了下面显示的测试。他的结果表明,PostgreSQL 和 MySQL 的运行速度大致相同。有关 Matt 的结果,请访问
已失效的 URL:http://www.sergeant.org/sqlite_vs_pgsync.html
SQLite 在与网站上显示的相同配置中进行了测试。它使用 -O6 优化和 -DNDEBUG=1 开关进行编译,该开关禁用 SQLite 代码中的许多“assert()”语句。-DNDEBUG=1 编译器选项使 SQLite 的速度大约提高了一倍。
所有测试都在其他方面处于静止状态的机器上进行。一个简单的 Tcl 脚本用于生成和运行所有测试。此 Tcl 脚本的副本可以在 SQLite 源代码树中的 tools/speedtest.tcl 文件中找到。
所有测试中报告的时间代表以秒为单位的挂钟时间。SQLite 报告了两个单独的时间值。第一个值是 SQLite 在其默认配置下启用完整磁盘同步时的值。启用同步后,SQLite 会在关键点执行 fsync() 系统调用(或等效调用),以确保关键数据已实际写入磁盘驱动器表面。如果操作系统崩溃或计算机在数据库更新过程中意外断电,则同步对于保证数据库的完整性是必要的。SQLite 报告的第二个时间是在禁用同步时。禁用同步后,SQLite 有时会快得多,但存在操作系统崩溃或意外断电可能损坏数据库的风险。一般来说,同步 SQLite 时间用于与 PostgreSQL(也同步)进行比较,异步 SQLite 时间用于与异步 MySQL 引擎进行比较。
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 行
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
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 完成。
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 行
INSERT 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 都快得多。
BEGIN;
CREATE TABLE t3(a INTEGER, b INTEGER, c VARCHAR(100));
CREATE INDEX i3 ON t3(c);
... 省略了 24998 行
INSERT 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),但其整体速度仍然更好。
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 慢,但最近的性能增强提高了它的速度,使其现在成为该组中最快的。
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%。
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 的未来版本在这里能做得更好。
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 仍然最快。
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 的后续版本中已经得到了解决。
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 的速度提高了一倍多。
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 的运行速度。
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 上。
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() 所需的额外时间。
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 比这两个都要快。
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 之前)在执行一系列 DELETE 后再执行新的 INSERT 时,性能会下降。如本测试所示,此问题现已解决。
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 操作,这可能是它在此测试中比其他数据库快得多的原因。
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 花费的时间稍长一些,这不会被视为一个大问题。
此页面上次修改于 2023-01-02 14:22:42 UTC