返回:SQLite—系列文章目录
上一篇:用于 SQLite 的异步 I/O 模块(二十四)
下一篇:SQLite—系列文章目录
注意:本文档非常非常旧。它描述了速度比较 SQLite、MySQL 和 PostgreSQL 的古老版本。
这里的数字已经变得毫无意义。此页面仅保留 作为历史文物。
摘要
进行了一系列测试来测量 SQLite 2.7.6、PostgreSQL 7.1.3 和 MySQL 3.23.41。 以下是一般情况 从这些实验中得出的结论:
-
SQLite 2.7.6 明显更快(有时高达 10 或 比默认的 PostgreSQL 7.1.3 安装快 20 倍) 在 RedHat 7.2 上执行最常见的操作。
-
SQLite 2.7.6 通常更快(有时 比 MySQL 3.23.41 快两倍以上 对于最常见的操作。
-
SQLite 执行 CREATE INDEX 或 DROP TABLE 的速度不如 其他数据库。但这并不被视为问题,因为 这些都是不常见的操作。
-
如果将多个操作组合在一起,则 SQLite 效果最佳 单个事务。
此处显示的结果带有以下注意事项:
-
这些测试没有试图衡量多用户性能或 优化涉及多个联接和子查询的复杂查询。
-
这些测试位于相对较小的(大约 14 兆字节)数据库上。 它们不衡量数据库引擎对更大问题的扩展程度。
测试环境
用于这些测试的平台是具有 1GB 或内存的 1.6GHz Athlon 和 IDE 磁盘驱动器。操作系统是 RedHat Linux 7.2,带有 一个库存内核。
默认情况下,使用的 PostgreSQL 和 MySQL 服务器在 红帽 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's 结果,访问
过时的 URL: http://www.sergeant.org/sqlite_vs_pgsync.html
SQLite在与出现的相同配置中进行了测试 在网站上。它是使用 -O6 优化和 -DNDEBUG=1 开关,它禁用了许多“assert()”语句 在 SQLite 代码中。-DNDEBUG=1 编译器选项大约翻了一番 SQLite的速度。
所有测试均在静止的机器上进行。 使用一个简单的 Tcl 脚本来生成和运行所有测试。 可以在 SQLite 源代码树中找到此 Tcl 脚本的副本 在文件 tools/speedtest.tcl 中。
所有测试中报告的时间代表挂钟时间 在几秒钟内。为 SQLite 报告两个单独的时间值。 第一个值是 SQLite 的默认配置,其中 已打开完整磁盘同步。打开同步 on,SQLite 执行 在关键点进行 fsync() 系统调用(或等效调用) 确保关键数据具有 实际上已写入磁盘驱动器表面。同步 是保证数据库完整性所必需的,如果 操作系统崩溃或计算机意外关闭电源 在数据库更新过程中。第二次报告SQLite是 关闭同步时。关闭同步后, SQLite 有时要快得多,但存在 操作系统崩溃或意外断电可能 损坏数据库。一般来说,同步SQLite 时间用于与 PostgreSQL 进行比较(这也是 synchronous)和异步 SQLite 时间用于 与异步MySQL引擎的比较。
测试 1:1000 个插入
创建表 t1(a INTEGER, b INTEGER, c VARCHAR(100));
插入 t1 值(1,13153,'一万三千一百五十三');
插入 t1 值(2,75560,'七万五千五百六十');
......省略 995 行 插入 t1 值(998,66289,'六万六千二百八十九');
插入 t1 值(999,24322,'24,322');
插入 t1 值(1000,94142,'九万四千一百四十二');
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 完成。
测试 2:事务中有 25000 个 INSERT
开始;
创建表 t2(a INTEGER, b INTEGER, c VARCHAR(100));
插入 t2 值(1,59672,'五万九千六百七十二');
......省略 24997 行
INSERT INTO t2 VALUES(24999,89569,'八万九千五百六十九');
插入 t2 值 (25000,94666,'94,666');
犯;
PostgreSQL: | 4.900 |
MySQL的: | 2.184 |
SQLite 2.7.6: | 0.914 |
SQLite 2.7.6 (nosync): | 0.757 |
当所有 INSERT 都放入事务中时,SQLite 不再需要 关闭并重新打开数据库,或使其在每个语句之间的缓存失效。 它也没有 必须做任何 fsync()s 直到最后。当解开束缚时 这样,SQLite 比 PostgreSQL 和 MySQL 快得多。
测试 3:索引表中有 25000 个 INSERT
开始;
创建表 t3(a INTEGER, b INTEGER, c VARCHAR(100));
在 t3(c) 上创建索引 i3;
......省略 24998 行
插入 t3 值(24999,88509,'八万八千五百九');
插入 t3 值 (25000,84791,'八万四千七百九十一');
犯;
PostgreSQL: | 8.175 |
MySQL的: | 3.197 |
SQLite 2.7.6: | 1.555 |
SQLite 2.7.6 (nosync): | 1.402 |
有报告称 SQLite 在索引表上表现不佳。 最近添加了此测试以反驳这些谣言。的确, SQLite在创建新索引条目方面不如其他引擎快 (请参阅下面的测试 6),但它的整体速度仍然更好。
测试 4:100 个没有索引的 SELECT
开始;
SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<1000;
从 t2 开始选择 count(*), avg(b),其中 b>=100 和 b<1100;
......省略了 96 行
SELECT count(*), avg(b) FROM t2 WHERE b>=9800 AND b<10800;
从 t2 开始选择 count(*),avg(b),其中 b>=9900 和 b<10900;
犯;
PostgreSQL: | 3.629 |
MySQL的: | 2.760 |
SQLite 2.7.6: | 2.494 |
SQLite 2.7.6 (nosync): | 2.526 |
此测试对没有索引的 25000 个条目表执行 100 次查询, 因此需要全表扫描。以前版本的 SQLite 用于 在此测试中比 PostgreSQL 和 MySQL 慢,但最近的表现 增强功能提高了它的速度,因此它现在是最快的 的组。
测试 5:字符串比较中的 100 个 SELECT
开始;
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 '%99%';
SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one hundred%';
犯;
PostgreSQL: | 13.409 |
MySQL的: | 4.640 |
SQLite 2.7.6: | 3.362 |
SQLite 2.7.6 (nosync): | 3.372 |
此测试仍执行 100 次全表扫描,但它使用 使用字符串比较而不是数值比较。 SQLite的速度是PostgreSQL的三倍以上,大约是PostgreSQL的30% 比MySQL更快。
测试 6:创建索引
在 t2(a) 上创建索引 i2a;
在 t2(b) 上创建索引 i2b;
PostgreSQL: | 0.381 |
MySQL的: | 0.318 |
SQLite 2.7.6: | 0.777 |
SQLite 2.7.6 (nosync): | 0.659 |
SQLite 在创建新索引方面速度较慢。这不是一个大问题 (因为新索引并不经常创建)但它是 正在处理中。希望SQLite的未来版本会做得更好 这里。
测试 7:5000 个带有索引的 SELECT
SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<100;
从 t2 开始选择 count(*),avg(b),其中 b>=100 和 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;
从 t2 开始选择 count(*), avg(b),其中 b>=499900 和 b<500000;
PostgreSQL: | 4.614 |
MySQL的: | 1.270 |
SQLite 2.7.6: | 1.121 |
SQLite 2.7.6 (nosync): | 1.162 |
当这三个数据库引擎都有要使用的索引时,它们的运行速度都更快。 但SQLite仍然是最快的。
测试 8:1000 个没有索引的更新
开始;
更新 t1 设置 b=b*2,其中 a>=0 和 a<10;
更新 t1 设置 b=b*2,其中 a>=10 和 a<20;
......省略 996 行 UPDATE t1 SET b=b*2 WHERE a>=9980 AND a<9990;
更新 t1 设置 b=b*2,其中 a>=9990 和 a<10000;
犯;
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 中。
测试 9:25000 个带有索引的更新
开始;
更新 t2 设置 b=468026 其中 a=1;
更新 t2 设置 b=121928 其中 a=2;
......省略 24996 行 UPDATE t2 SET b=35065 WHERE a=24999;
更新 t2 设置 b=347393 其中 a=25000;
犯;
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的优化还有更多 更新速度提高了一倍以上。
测试 10:25000 个带有索引的文本 UPDATE
开始;
更新 t2 SET c='148,382' WHERE a=1;
更新 t2 SET c='366,502' WHERE a=2;
......省略 24996 行 UPDATE t2 SET c='383,999' WHERE a=24999;
更新 t2 SET c='256,830' WHERE a=25000;
犯;
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 快 20 倍以上。
公平地说,PostgreSQL开始在这个测试中失败。一个 知识渊博的管理员也许能够让 PostgreSQL 运行很多 通过稍微调整和调整服务器来加快速度。
测试 11:从 SELECT 插入
开始;
插入 t1 从 t2 中选择 b,a,c;
插入 t2 从 t1 中选择 b,a,c;
犯;
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 上花费了时间。
测试 12:不带索引的 DELETE
从 t2 中删除,其中 c 像 '%fifty%';
PostgreSQL: | 1.509 |
MySQL的: | 0.975 |
SQLite 2.7.6: | 4.004 |
SQLite 2.7.6 (nosync): | 0.560 |
SQLite 的同步版本是本次测试中组中最慢的, 但异步版本是最快的。 区别在于执行 fsync() 所需的额外时间。
测试 13:使用索引执行 DELETE 操作
从 t2 中删除,其中 A>10 和 A<20000;
PostgreSQL: | 1.316 |
MySQL的: | 2.262 |
SQLite 2.7.6: | 2.068 |
SQLite 2.7.6 (nosync): | 0.752 |
这个测试很重要,因为它是为数不多的 PostgreSQL 比 MySQL 快。异步 SQLite 是, 但是,比其他两个都快。
测试 14:大 DELETE 之后的大 INSERT
插入 t2 选择 * 从 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。如此测试所示, 问题现已解决。
测试 15:一个大的 DELETE,后跟许多小的 INSERT
开始;
从 t1 中删除;
插入 t1 值(1,10719,'10,719');
......省略 11997 行
插入 t1 值(11999,72836,'七万二千八百三十六');
插入 t1 值(12000,64231,'六万四千二百三十一');
犯;
PostgreSQL: | 4.556 |
MySQL的: | 1.704 |
SQLite 2.7.6: | 0.618 |
SQLite 2.7.6 (nosync): | 0.406 |
SQLite 非常擅长在事务中执行 INSERT,这可能 解释了为什么它在这个测试中比其他数据库快得多。
测试 16:删除表
删除表 t1;
下降表 t2;
下降表 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需要更长的时间,那不被视为一个大问题。