Pull to refresh

Сравнение производительности MongoDB vs PostgreSQL. Часть I: No index

High performance *PostgreSQL *MongoDB *
Recovery mode
Sandbox
Не так давно встала необходимость самостоятельно оценить производительность и ресурсоёмкость всё более набирающей популярность noSQL СУБД MongoDB. Для наглядности решил заодно сравнить её с производительностью PostgreSQL, которая также небезызвестна и активно используется.

Среда обитания


Тесты производились на виртуальном сервере со следующими характеристиками:

cpu: 4 ядра по 2GHz
RAM: 2GB
OS: Centos 6.4

mongoDB

Версия: 2.4.3

Конфигурация:

logpath=/xxx/mongod.log
logappend=true
fork = true
dbpath=/xxx/mongo
pidfilepath = /xxx/mongod.pid


Параметры при старте mongod:

OPTIONS=" -f $CONFIGFILE"


PostgreSQL:

Версия: 8.4.13

Конфигурация:

shared_buffers = 1GB
max_prepared_transactions = 0
work_mem = 64MB
maintenance_work_mem = 512MB
effective_cache_size = 512MB


Подопытные


Решено было создать и добавить в тестовую коллекцию (а для PostreSQL — таблицу) ровно 1 000 000 записей. Алгоритм генерирования записей был один и тот же что для MongoDB, что для PostreSQL. Для большего приближения к «реальности» был введен элемент случайности. В итоге тестовый объект имел следующую структуру:

  • id — случайное целое число в диапазоне от 1 000 до 10 000 000
  • title — случайная строка (кириллица) длиной от 10 до 50 символов
  • text — случайно сгенерированный текст длиной от 1 000 до 2 000 символов
  • floatvalue — случайное дробное число в диапазоне от 1 000 до 10 000 000


Для усреднения времени вставки, миллион записей был разбит на 4 части по 250 000 записей. На первом этапе эксперимента никакие индексы не использовались.

Замеры времени на вставку дали следующие результаты:

MongoDB

(Для генерации использовался нативный JS. Время генерации включено в общее время вставки)

Insert 250 000 records complete! Total time: 62.788 sec
Insert 250 000 records complete! Total time: 62.481 sec
Insert 250 000 records complete! Total time: 62.916 sec
Insert 250 000 records complete! Total time: 61.565 sec

Average time: 62.4375 sec


PostgreSQL

(Для генерации использовался PHP. Время генерации не включено в общее время вставки)

psql -d prefTest -f 250k.p1.sql (Total time: 326.377 sec)
psql -d prefTest -f 250k.p2.sql (Total time: 326.646 sec)
psql -d prefTest -f 250k.p3.sql (Total time:  327.726 sec)
psql -d prefTest -f 250k.p4.sql (Total time:  327.039 sec)

Average time: 326.947 sec


Эксперимент I: No index


Для эксперимента были взяты следующие запросы:

MongoDB

  1. db.tmp.find({id:{$gt:10000}}) /* Сравнение целых чисел */
  2. db.tmp.find({floatvalue: {$lt:300000}}) /* Сравнение дробных чисел */
  3. db.tmp.find({title:/^А/}).explain() /* Заголовок начинается с «А» */
  4. db.tmp.find({text:/хабр/}).explain() /* Поиск вхождения строки «хабр» в тексте */

PostgreSQL (всё то же самое, но в SQL синтаксисе)

  1. select * from tmp where id>10000
  2. select * from tmp where floatvalue<300000
  3. select * from tmp where title like 'А%'
  4. select * from tmp where text like '%хабр%'


В процессе эксперимента для каждого запроса измерялось не только время выполнения запросов но и средние показатели использования ресурсов (процессорная нагрузка и объем оперативной памяти).

Для более наглядного сравнения быстродействия операций был введен атрибут скорость (количество обработанных объектов/записей в секунду).

Результат сравнения скорости операций в таблице/коллекции приведен в диаграмме:

image

Здесь можно видеть, что максимальной разницы в производительности MongoDB достигает за счет скорости вставки (4004 объекта в секунду против 765 у PostgreSQL). А с операцией выборки по параметру id PostgreSQL вообще не справился, все попытки приводили к process terminated (повышение параметров shared_buffers и т.п. ни к чему не приводили, глубже я копать не стал, ибо не принципиально).

Естественно, такой отрыв MongoDB обусловлен и более активным использованием процессорного времени. Средние цифры по всем запросам выборки:

MongoDB
  • 30% — 40% нагрузки на процессор
  • 704 — 706 МБ используемой оперативной памяти

В то время как PostgreSQL
  • 5% — 25% нагрузки на процессор
  • 550 — 1000 МБ используемой оперативной памяти

Если усреднить, то по использованию оперативной памяти между этими СУБД нет особой разницы при выборке. Однако при вставке MongoDB, опять же, использует её гораздо активнее (1407 МБ, против 745 МБ у PostgreSQL).

Но, как мы помним, это все результаты для запросов не использующих индекс. В реальных условиях сложно найти разработчиков, которые не оптимизируют свои запросы теми или иными индексами. Поэтому вторым этапом нашего эксперимента стало добавление нескольких индексов в коллекцию MongoDB и таблицу PostgreSQL. Результаты его оказались весьма… мм… непредсказуемыми. О них я обязательно расскажу в следующей части: Сравнение производительности MongoDB vs PostgreSQL. Часть II: Index, а также подведу общие итоги тестирования с результирующими табличками и графиками.
Tags:
Hubs:
Total votes 57: ↑22 and ↓35 -13
Views 48K
Comments Comments 25