RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

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 работает немного дольше, это не рассматривается как большая проблема.