Small. Fast. Reliable. Choose any three.
Сравнение скорости базы данных
Примечание: Этот документ очень очень стар. Это описывает сравнение скорости
между архаичными версиями SQLite, MySQL и PostgreSQL.
Числа здесь стали бессмысленными. Эта страница была сохранена только
как исторический экспонат.
Резюме
Ряд тестов был запущен, чтобы измерить относительный уровень SQLite 2.7.6,
PostgreSQL 7.1.3 и MySQL 3.23.41. Следующее это общие выводы, сделанные
из этих экспериментов:
SQLite 2.7.6 значительно быстрее (иногда целых в 10 или 20 раз
быстрее), чем установка PostgreSQL 7.1.3 по умолчанию на RedHat 7.2
для наиболее распространенных операций.
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
(версия 7.1.3 PostgreSQL и версия 3.23.41 MySQL). Никакое усилие не было
приложено, чтобы настроить эти СУБД. Отметьте в особенности, что
конфигурация MySQL на RedHat 7.2 по умолчанию не поддерживает транзакции.
Необходимость поддержать транзакции дает MySQL большое преимущество скорости,
но SQLite все еще в состоянии держаться в отрыве на большинстве тестов.
Мне говорят, что конфигурация PostgreSQL по умолчанию в RedHat 7.3
излишне консервативна (это разработано, чтобы работать с
машиной с 8 МБ RAM), и PostgreSQL мог бы работать намного быстрее с некоторой
хорошей настройкой конфигурации. Matt Sergeant сообщает, что настроил свою
установку PostgreSQL и запустил повторно тесты, показанные ниже.
Его результаты показывают что PostgreSQL и MySQL работают на приблизительно
той же самой скорости. Для результатов посмотрите
Obsolete URL: http://www.sergeant.org/sqlite_vs_pgsync.html
SQLite был проверен в той же самой конфигурации, как
на веб-сайте. Это было собрано с оптимизацией -O6 и -DNDEBUG=1,
который отключает многие "assert()" в коде SQLite.
Параметр -DNDEBUG=1 примерно удваивает скорость SQLite.
Все тесты проводятся на одинаковой в других отношениях машине.
Простой скрипт Tcl использовался, чтобы произвести и запустить все тесты.
Копия этого скрипта Tcl может быть найдена в исходном дереве SQLite в файле
tools/speedtest.tcl.
Времена, о которых сообщают относительно всех тестов, представляют время
настенных часов в секундах. О двух отдельных временных значениях
сообщают для SQLite. Первое для SQLite в конфигурации по умолчанию с
включенной полной дисковой синхронизацией.
С включенной синхронизацией SQLite выполняет системный вызов
fsync() (или эквивалент) в ключевых пунктах, чтобы удостовериться, что
критические данные были на самом деле написаны на диск.
Синхронизация необходима, чтобы гарантировать целостность базы данных, если
операционная система терпит крах или питание компьютера отключается
неожиданно посреди обновления базы данных.
Второй раз, о котором сообщают для SQLite, это
когда синхронизация выключена. С выключенной синхронизацией SQLite
иногда намного быстрее, но есть риск, что катастрофа операционной системы или
неожиданный перебой в питании могли повредить базу данных. Вообще говоря,
синхронные времена SQLite для сравнения с PostgreSQL (который также
синхронен), и асинхронные времена SQLite для
сравнения с асинхронным MySQL.
Тест 1: 1000 INSERT
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 lines omitted
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 на диске.
Тест 2: 25000 INSERT в транзакции
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 lines omitted
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.
Тест 3: 25000 INSERT в индексируемую таблицу
BEGIN;
CREATE TABLE t3(a INTEGER, b INTEGER, c VARCHAR(100));
CREATE INDEX i3 ON t3(c);
... 24998 lines omitted
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), но его общая скорость еще лучше.
Тест 4: 100 SELECT без индекса
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 lines omitted
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
|
Этот тест делает 100 запросов на 25000 записей таблицы без индекса, таким
образом требуя полного сканирования таблицы. Предыдущие версии SQLite раньше
были медленнее, чем PostgreSQL и MySQL на этом тесте, но недавние
улучшения увеличили скорость так, чтобы это было самым быстрым из группы.
Тест 5: 100 SELECT на сравнении строк
BEGIN;
SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one%';
SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%two%';
... 96 lines omitted
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 здесь и приблизительно на 30% быстрее, чем MySQL.
Тест 6: Создание индекса
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
добьются большего успеха здесь.
Тест 7: 5000 SELECT с индексом
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 lines omitted
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 является все еще самым быстрым.
Тест 8: 1000 UPDATE без индексов
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 lines omitted
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.
Тест 9: 25000 UPDATE с индексом
BEGIN;
UPDATE t2 SET b=468026 WHERE a=1;
UPDATE t2 SET b=121928 WHERE a=2;
... 24996 lines omitted
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
|
Уже версия SQLite 2.7.0 работала приблизительно с той же самой скоростью,
как MySQL на этом тесте. Но недавняя оптимизация SQLite более чем
удвоила скорость UPDATE.
Тест 10: 25000 текстовых 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 lines omitted
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 работать намного
быстрее, настраивая сервер.
Тест 11: INSERT из 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 диска.
Тест 12: DELETE без индекса
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().
Тест 13: DELETE без индекса
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, однако, быстрее.
Тест 14: Большой INSERT после большого 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) показали бы
уменьшающуюся производительность после последовательности DELETE,
сопровождаемой новым INSERT. Как этот тест показывает,
проблема была решена.
Тест 15: Большой DELETE, сопровождаемый многими маленькими INSERT
BEGIN;
DELETE FROM t1;
INSERT INTO t1 VALUES(1,10719,'ten thousand seven hundred nineteen');
... 11997 lines omitted
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 в транзакции, которая, вероятно,
объясняет, почему это настолько быстрее, чем другие базы
данных в этом тесте.
Тест 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 работает немного дольше, это не рассматривается
как большая проблема.
|