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

    Продолжение, начало здесь.

    Эксперимент II: Index



    Для этого эксперимента мы создали индексы на полях id и floatvalue (текстовые поля опустили, тему полнотекстового индекса затрагивать не будем, так как это материал для отдельной статьи). В качестве запросов использовались выборки из диапазонов:

    • 10 000 < id < 100 000
    • 200 000 < floatvalue < 300 000


    Но для начала, необходимо оценить, насколько упала скорость вставки после добавления индексов. Для этого добавим еще по 250 000 записей в MongoDB и POstgreSQL.



    MongoDB

    Insert 250000 records complete! Total time: 69.453 sec
    


    PostgreSQL

    psql -d prefTest -f 250k.p5.sql (Total time: 466.153 sec)
    


    После несложных вычислений можно понять, что по скорости вставки MongoDB остался бесспорным лидером: после добавления индексов его скорость вставки упала всего на ~10% и составила 3600 объектов в секунду. Тогда как скорость вставки у PostgreSQL упала на ~30% и составила около 536 записей в секунду.

    Хотелось бы, чтобы ситуация с выборкой сложилась аналогичным образом. Выполняем следующие запросы:

    MongoDB

    1. db.tmp.find({$and:[{id:{$gt:10000}},{id:{$lt:100000}}]})
    2. db.tmp.find({$and:[{floatvalue: {$lt:300000}},{floatvalue: {$gt:200000}}]})


    PostgreSQL

    1. select * from tmp where id>10000 and id<100000
    2. select * from tmp where floatvalue<300000 and floatvalue>200000


    Однако после сравнения скорости выполнения операций ситуация по выборкам изменилась в пользу PostgreSQL:

    image

    Также стоит отметить, что при выборке не из диапазона, а с указанием конкретных цифр (н.п. floatvalue=1234567.76545) обе СУБД показали результат в 0 миллисекунд. Поэтому такие операции здесь даже не рассматриваются. Это к вопросу о разумном использовании индексов в соответствии с планируемыми условиями выборки. Здесь же индексы и запросы используются только с целью нагрузочного тестирования.

    Еще одним откровением стало, что при использовании индексов MongoDB настолько резко снижает потребление процессорного времени (до 1-2 % против 30-40 % при поиске без индексации), что даже обгоняет в этом PostgreSQL (снижение до 4-14 % против 5-25 %).

    Итоги



    Прежде чем что-то подытоживать, делюсь, как и обещал результирующей табличкой и диаграммами потребления ресурсов по запросам:

    image

    image

    image

    А теперь о результатах.

    Невооруженным взглядом можно сразу заметить одно преимущество MongoDB перед PostgreSQL: скорость вставки. Она практически на порядок выше как с использованием индексов, так и без них. Более того, использование индексов не так значительно её снижает (всего на ~10% против 30%-ного снижения у PostgreSQL). Это действительно превосходный результат! Но… как часто вы используете вставку относительно выборки (по всевозможным условиям)?

    При выборке из коллекции без индексов MongoDB также лидирует, хотя уже и не столь значительно. Неплохо! Но... как часто вы работаете с таблицами без индексов?

    Не подумайте, что своими вопросами я пытаюсь отвернуть вас от noSQL СУБД. Таблицы без индексов (не имею ввиду первичный) имеют место быть в тех или иных решениях. Приоритет скорости вставки для некоторых задач — тоже весьма реален и, более того, иногда очень востребован. Вопрос в том, нужно ли это конкретно вам? Конретно для вашей текущей задачи? Это (весьма поверхностное) тестирование не призвано дать ответ на, не скрою, довольно популярный вопрос «Что лучше SQL или noSQL?». Оно призвано навести вас на размышления, оценить потребности и возможности при выборе того или иного решения для той или иной задачи.

    Напоследок скажу, что мы, например, используем оба типа СУБД, в зависимости от структуры данных, целей и вариантов работы с ними. Комплексный подход гораздо лучше и позволяет максимально оптимально работать с любыми данными.
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 27
    • +4
      Опять вопрос из серии «Кто сильнее, кит или слон?». Ну нельзя их сравнивать. Они обеспечивают совершенно разный функционал. Mongo vs Postgre вопрос не скоростей работы, а архитектуры вашего приложения, ваших задач и ваших методов их решения.
      • –2
        Автору можно дать еще один иронический совет для «ускорения записи/чтения» — попробуйте писать в файлы. И сравнивать с полноценной СУБД.
        У вас даже график построить не получится :-) Но собственно и полноценное приложение на фалах будет построить очень не просто.
        Для каждой задачи — свой инструмент.
        • –3
          А какая у меня мотивация может быть юзать mongo кроме скорости?
          • +2
            Например, ненормализованые данные с переменчивой структурой, не?
        • +2
          Все тесты проводились в однопоточном режиме?
          Может, стоит провести многопоточный тест?
          • +2
            В случае монго и операций вставки это будет очень актуально :) Если учесть, что монго лочит при записи всю базу.
          • 0
            Как часто Вы не кешируете результаты запросов в нагруженном проекте? :)
          • 0
            Интересно было-бы увидеть тесты параллельных операций вставки и выборки для этих СУБД.
            • +1
              MongoDB без getLastError() и без реплик ну никак не может сравниваться с PostgreSQL с fsync'ом, т.к. без этого монго не даёт никаких гарантий, что данные реально записались и не будут потеряны.
              • 0
                thebuild.com/presentations/pg-as-nosql-pgday-fosdem-2013.pdf
                Тут еще интересные цифры.
                • +2
                  Ваши тесты без отключения синхронизации с диском в postgres, либо без включения её же в mogno — хрень. К тому же, как уже писали, данные СУБД решают различные классы задач, так что сравнивать их некорректно.
                  • –2
                    Уверен что большинство мелких и средних (что греха таить, и часть крупных) проектов в сети работают с СУБД «из коробки», т.е. с теми настройками какие заложил по умолчанию производитель. Учитывая этот фактор, сравнение коробочных версий весьма корректно. Не зря в статье написано что это весьма поверхностное тестирование. Но буду весьма рад, если вы сможете «разогнать» PostgreSQL (без ущерба стабильности системы) и выложить более глубокий анализ его максимальной производительности.

                    Что же до классов задач — это не совсем так. Одну и ту же задачу можно решить разными способами. Тот же Foursquare вполне же можно было написать и с использованием реляционных БД, согласитесь? )
                    • +1
                      Уверен что большинство мелких и средних (что греха таить, и часть крупных) проектов в сети работают с СУБД «из коробки»

                      Мда, искренне сочувствую я тем проектам, где вы это встречали. Я лично не встречал ни одного проекта с настройкой СУБД по умолчанию.
                      если вы сможете «разогнать» PostgreSQL (без ущерба стабильности системы)

                      Как бы монго без реплик тоже стабильностью не блещет, в продакшн без этого её никто ставить не будет.
                      • 0
                        >>Как бы монго без реплик тоже стабильностью не блещет

                        Пруфлинк, пожалуйста. Интересно откуда этот слух пошел.
                        • 0
                          docs.mongodb.org/manual/administration/production-notes/
                          docs.mongodb.org/manual/replication/
                          Replica sets provide redundancy and high availability, and are the basis for all production deployments

                          И это не слух, а реальный опыт.
                          • –1
                            Тут всего лишь сказано что с репликацией обеспечивается большая надежность.

                            В случае с PostgreSQL всё то же самое. Или вы хотите сказать, что использование репликаций в PostgreSQL — бесполезное занятие? Для чего тогда ему эта функциональность?
                      • 0
                        «настройки по умолчанию» у постгреса такие, что бы он везде запустился. Учитывая этот фактор, тестировать постгреса с этими настройками смысла вообще нет.

                        PostgreSQL ships with a basic configuration tuned for wide compatibility rather than performance. Odds are good the default parameters are very undersized for your system.
                        отсюда
                    • 0
                      Повторю комментарий к предыдущей статье:

                      1) Слишком старые версии серверов
                      2) Слишком несоотносимые настройки, особенно на запись (хотябы fsync=off в postgresql или synchronous_commit=off)
                      3) Код тестов тоже не привели
                      • 0
                        Как вы производили вставки в MongoDB? По-умолчанию она не ждет ответа об успешности записи, поэтому создав 300000 записей, они еще могли в фоне создаваться несколько секунд. Тоже самое с удалением и другими операциями.
                        • 0
                          Видимо вы имеет в виду Write Concern ( docs.mongodb.org/manual/core/write-concern/ ) но не совсем понимаете его принципы.

                          Во-первых, никто не продолжает вставку в фоне. Write concern (далее будем называет его просто w) только определяет уровни оповещения об ошибках записи. Если операция завершена, значит она завершена. А вот нужно ли сообщать об ошибках в процессе операции — это уже другой вопрос.

                          Во-вторых, w по умолчанию выставлен не в -1 (Errors Ignored), и даже не в 0 (Unacknowledged), а в 1 (Acknowledged). Прибавим к этому еще и включенное по умолчанию журналирование (аналог полюбившегося здешними комментаторами fsync), мы получаем следующую картину:

                          docs.mongodb.org/manual/_images/crud-write-concern-journal.png

                          Полагаю, что этого более чем достаточно, чтобы сравнение «коробочного» MongoDB с «коробочным» же PostgreSQL имело место быть.
                          Печально, что большинство пользователей просто как «по-заученному» твердят про какие-то fsync=off, репликацию, отсутствие у монги getLastError, нестабильности этой СУБД и т.п. совершенно не пытаясь проверить актуальность своих познаний.

                          UPD: К сожалению тэги не сработали, пришлось вставить просто ссылками.
                          • 0
                            По-моему этот режим не проверяет записалась ли физически информация на диск, а кстати такой режим записи в mongo есть и он такой же по скорости как и в Postgres. Я очень давно сравнивал.
                            • –1
                              Давайте всё же без «по-моему» )
                              • 0
                                Ну не забывайте еще что Postgres все это выполняет в транзакции. Не реализуя транзакции, мы прибавляем в производительности. Я пробовал и то и другое, у меня есть проекты и на Mongo и на обычных БД. Без транзакций жить тяжко конечно. Но со вставкой явно у вас что-то не то, не может так сильно проигрывать Postgres. Я помню первый ажиотаж, когда все трубили, что монго в 10 раз быстрее делает выборки, оказалось банально что вся нагрузка происходит в fetch. Тут нужно еще раз перепроверить. Может сравнить c Mysql.

                                Я еще сравнивал когда-то скорость обновления одного поля в Mongo, через set или inc (через атомарные операции), так вот они еще быстрее, у меня выходило так, что монго спокойно обрабатывал такую операции на 500 000 меньше чем за секунду.
                                • 0
                                  Согласен. Но транзакции — нужны только при «релятивистском» подходе в проектировании.
                                  Также согласен и с тем что тут сравнение действительно слишком общее и неполноценное.
                                  Есть идея создать два абсолютно одинаковых (по доступной функциональности) проекта, но сделать различие в логике построения — один будет использовать Монго, а второй PostgreSQL со всеми вытекающими (транзакции, джойны и т.д.).

                                  А потом прогнать какой-нибудь siege и/или ab. Тут и многопоточность и приближение к «боевым» условиям (те же блокировки, к примеру).

                                  Хотя не знаю, стоит ли игра свеч…
                                  • 0
                                    Еще я вспомнил одну неприятную вещь про Mongodb, любая запись блокирует операции чтения то ли для всей базы, то ли для таблицы. В результате, если у нас приложение, которое часто что-то пишет в базу, то проседают выборки из базы, из-за блокировок.

                                    Единственный способ снизить этот недостаток, создать реплики.
                                    • –1
                                      Ну не забывайте что в постгресе также есть блокировки. Более того там еще более печальный эффект есть — deadlock называется: www.postgresql.org/docs/current/static/explicit-locking.html#LOCKING-DEADLOCKS

                                      Так что «неприятные вещи» есть везде. Вопрос уже не в самой СУБД, а в проектировании таких образом чтобы снизить вероятность этих «неприятных вещей».

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.