войти зарегистрироваться

Web-разработка whois

индекс
184,85

MongoDB и MySQL в Ruby и PHP

imageНекоторое время назад довольно заинтересовался разработкой для MongoDB и провел некоторые бенчмарки в сравнении с MySQL.
Изначально только в Ruby, но, когда результаты изумили (в худшую сторону), то и в PHP, для сравнения.
Может быть, это кому-то сэкономит некоторое время.

Исходные данные:
  • Система:$ uname -a
    Linux pavlin.ik 2.6.31-gentoo-r4 #1 SMP Sun Nov 1 18:21:31 MSK 2009 i686 Intel® Core(TM)2 Duo CPU T5450 @ 1.66GHz GenuineIntel GNU/Linux
  • MongoDB v. 1.0.1
  • Gems:
    • gem mongo (0.16)
    • gem mongo_ext (0.16)
    • gem mysql (2.8.1)
    Ruby:PHP 5.2.11-pl0-gentoo with Suhosin-Patch 0.9.7 (cli)
Исходный код тестов есть тут: http://github.com/latrommi/benchmarking

Собственно, результаты:
image

Вывод один: это не значит, что MongoDB хуже MySQL, это значит, что для нее ещё не написано нормального, быстрого драйвера для Ruby :)

P.S. будет круто, если кто-то проведет аналогичные тесты для Python.
P.P.S. пользуясь случаем, передаю привет TravisBickle ;)

комментарии (57)

  • Спасибо за информацию.
    Не могли бы вы добавить график mysql-php?
    • Присоединяюсь к вопросу
    • Добавил.
      PHP, Ruby 1.8, Ruby 1.9, Ruby Enterprise.
      MySQL и MongoDB для каждого.
      • Спасибо
  • А чем рисовался график?
  • Ruby не знаю и могу ошибаться, но, вроде, тестировалась только запись в базу. Вы не погли бы протестировать также, но только на чтение?
    • Поддерживаю. На самом деле результаты на чтение даже более интересы, нежели insert.
      • Кому что. У меня была цель сначала протестировать именно insert и именно в реальных условиях (в противовес вставке нормализованных данных в реляционную БД) и только потом find.
        • Если ваше гипотетическое приложение будет использовать коллекцию в большей степени для записи, а не для чтения, то используйте Capped Collections в Mongo
    • НЛО прилетело и опубликовало эту надпись здесь.
      • Имхо, глупость с выключением. О том что данные в Монго надо будет чинить сказано в документации. Вам это критично? Тогда не используйте. Лично у меня на сервере есть ИБП, чего и всем рекомендую :)
        • НЛО прилетело и опубликовало эту надпись здесь.
          • mysql-myisam тоже не бд?
            mongodb использует mmap()
            • НЛО прилетело и опубликовало эту надпись здесь.
            • > mysql-myisam тоже не бд?
              Да, это не БД. Это записная книжка с SQL-интерфейсом. Для серьезных проектов лучше использовать innodb.
              • почему не bdb xtradb или NitroEDB или BrightHouse? :)
                И если на сервере не журналируемая ФС, то innodb на этом севере тоже не бд?
                • Да все что угодно, хоть постгрес, только не маисам :)
                  • это все предрассудки :) myisam хорошо выполняет предназначенные для него задачи — например, это может быть хорошая ферма slave-ов для запросов с беков — лучше чем innodb.
          • Я к тому, что это не неприятный сюрприз. А задокументированная особенность. Да, она не транзакционная. Да, использовать ее для важных данных не рекомендуют и сами разработчики. Но есть много приложений не столь критичных. Зато у Монго такиииие возможности шардинга, что уххх… И это только начало. Все зависит от того для чего использовать. И как сказал товарищ выше — там где MyISAM часто бывает удобней использовать Монго.
      • Максим, да, это было бы интересным, но, уже благодаря этому, первоначальному и примитивному исследованию я понял, что MongoDB рановато пока использовать и продолжать тестирование буду только тогда, когда он обновится.

        Во-первых, он пару раз просто упал во время тестов (в логах не было ничего, даже segmentation fault), а во вторых я заинтересован исключительно в Ruby, поэтому подожду, когда хотя-бы однопоточный уровень скорости записи будет соизмерим с PHP, на котором показано, что гипотетический драйвер MongoDB способен на большее.

        В любом случае, продолжение следует.
        • НЛО прилетело и опубликовало эту надпись здесь.
          • Всё по TCP. Над причиной еще предстоит подумать :-)
            • НЛО прилетело и опубликовало эту надпись здесь.
        • хотя-бы однопоточный уровень скорости записи будет соизмерим с PHP


          Я полагаю, что мы обсуждаем web-разработку, а в этом случае делать выводы на основе этого теста некорректно. Единственное, что он объективно показывает, что взаимодействие MongoDB с Ruby более медленное, чем взаимодействие с PHP. А нужно сравнивать поведение MySQL и MongoDB. Я уверен в том, что результат в реальных многопоточных условиях может быть другим. И если MongoDB будет быстрее MySQL, то какая разница в том, что в PHP он работает быстрее.
  • а напишите выводы по полученным результатам и графикам… как в лабораторной работе в институте, а то возникает ощущение незаконченности исследования
    • И оценку поставьте, ага.
  • Тест очень синтетический — идет последовательная запись в базу. Это объясняет, почему графики так примитивно выглядят (если ось абсцисс будет в обычной шкале, то мы получим прямые с разным коэффициентом наклона). Если рассматривать MongoDB как замену (дополнение) MySQL в web разработке, то тестироваться должны параллельные запись/чтение.
    • habrahabr.ru/blogs/webdev/74683/#comment_2158418
      • Все зависит от задачи. Делать выводы по одному этому исследованию некорректно. Можно ведь и жигули с суперкаром тестировать на бездорожье и сделать вывод о том, что разницы в принципе нет.
  • Было бы гораздо нагляднее предствить график «Mongo vs MySQL» в виде столбчатой диаграммы. То, что увеличение количества операций увеличивает время выполнения и ежу понятно.
    • При таком количестве рядов диаграмма просто замусорится, если сделать столбчатую диаграмму. В принципе и так все видно, надо не просто смотреть на график вдоль оси абсцисс, а просто сравнивать значения графиков в одной и той же точке (т.е. смотреть на изменение величины вдоль оси ординат).
      • Ничего подобного. Данные можно сгруппировать по языкам/версиям. Для осознания результатов достаточно только, к примеру 100000, остальное — информационный хлам. Если уж так хочется его использовать, нужно как-то обработать результаты и нормировать их по количеству операций. Графики показывают только динамику процесса. К примеру на 10000 совершенно не понятно чего лучше, а чего хуже.
        • Ага. Я так и сделал. Посмотри ниже. ;)
  • Вот есть еще тесты от самих разработчиков www.mongodb.org/display/DOCS/Performance+Testing.
    Но ваши лучше тем что есть исходники :)
  • Хм, а что если у меня скажем php 5.3 у которой уже типа свой драйвер под MySQL который с ним не плохо я вам скажу работает?
    • Вообще-то PHP тут притянут просто для сравнения, на его месте так же безопасно мог бы чувствовать себя, например, Python. В тестировании мне интересен исключительно Ruby.

      Если вам не безразличны бенчмарки среди движков PHP, вы можете проделать их сами.
      Я специально оставил исходники в распоряжении читателя :-)
  • Построил еще несколько графиков по приведенным данным. Извините, что картинки выводятся сразу, но они легковесные: по 8 Кб всего.

    1. Зависимость времени вставки от количества вставок.
    Free Image Hosting at www.ImageShack.us
    Зависимость линейная, как и предполагал shai_xylyd. Видно, что с MySQL у Ruby дела обстоят одинаково, независимо от версии, а вот с MongoDB у Ruby 1.8 самый низкий результат (максимальное время вставки). PHP, тем не менее, пока может дать фору Ruby в работе с базами (по крайней мере при последовательных вставках).

    2. Сравнение времени вставки 100k записей в MySQL и в MongoDB
    Free Image Hosting at www.ImageShack.us
    Ну тут, в принципе пояснять и нечего. Все и так понятно.

    3. Отношение времени, затраченного на вставку в MySQL к времени, ушедшему на вставку в MongoDB.
    Free Image Hosting at www.ImageShack.us
    Для Ruby все почти стабильно. А вот для PHP с ростом количества вставок это соотношение снижается. Может кто-нибудь объяснить почему?
    • Круто! Особенно последний график интересен.
    • Может потому, что при вставке многих обьектов возрастает и количество ключей их свойств? Оно ведь тоже растет. Рекомендуется использовать очень короткие ключи вроде «datePublished» → «dP».
  • Да, кстати, если уж замерять php, то неплохо было бы замерить php 5.3, там все-таки mysqlnd и это совсем не одно и то же как в 5.2.х
  • вы ос и mysql оптимизировали?

    Покажите db.collection().findone из монго, мне кажется там может быть проблема с типом.
    • Нет, всё из коробки. Правда для Gentoo понятие «из коробки» несколько растяжимое :)

      Покажите db.collection().findone из монго, мне кажется там может быть проблема с типом.

      > db.bmdb.findOne()
      {"_id": ObjectId( «4af78bb8eb470d23710952bd»), «stub»: «i am empty init doc»}
      • а count где?
        • Сорри, не глядя скопипастил инитовую запись.
          Вот, например, первая:

          > db.bmdb.find({«count»:1});
          {"_id": ObjectId( «4af78c6aeb470d23710952bf»), «text»: «i am any text», «count»: 1, «coords»: {«x»: 100, «y»: 200, «z»: 1}}
          • еще я смотрю в монго не safe insert используется, т.е. прием команды не ждет результат вставки.
            во время тестов где бутылочное горлышко для mongo и mysql
  • куда-то пропали исходники… nginx выдал not found
    но все же посмотреть успел

    графики вставки не так интересны, как графики выборки (или лучше даже вместе)
    можно написать вставку просто в текстовый файл — и будет заметно быстрее, но явно не есть преимуществом такого подхода

    а еще третий график в коментах плохо соответствует первому… пхп и руби ведут себя линейно в первом графике, а отношение — не очень… странно :)

    жду с нетерпением графика зависимости времени вставок и времени выборок от количества имеющихся в базе записей
    • это сам сервис github лагает.
      от количества записей скорость не зависит — сложность операций O(1) в обоих случаях.
      • я себе представлял такую ситуацию:
        от роста количества записей растут индексы, вставка нового индекса — это обычно O(log n)
        но если в многодб линейно, то что же с индексами?
        • ну не совсем так, b-tree в чистом виде мало кто использует, используется «буфферизированные» вставки для обычных индексов, в этом примере вообще только unique индексы, т.е. это по идее вообще аналог key-value бд. Для выборки сложностью все таки будет одинаковая, для записи она будет немного падать, но на фоне работы с жестким диском выглядит как линейная.

          По опыту — сначала у обоих всегда ложится винт если есть запись и сеть если нет, по расходу cpu mongo выигрывает. mysql пока лучше работает с сокетами и конкурентностью, но у них там планов на следующий год вагон.
  • У меня возникло подозрение, что Mongo — документоориентированная база данных, а значит Ваш тест не совсем корректен. Может быть cтоит тестировать при сохранении больших объектов?
  • Правильно ли я понял.
    Тестирование проводилось на одной машине?

    Если так, то это фигня а не тест.

    БД, неважно какая, поделила ресурсы с движком.
    Руби, особенно 1.8 ест побольше чем тот же пых. Соответственно базе осталось меньше. Вот она и сливает. И дрова тут не особо причем.
    • Драйвер это понятие из архитектуры самой mongo. сама субд там оперирует бинарными объектами, а интерфес для работы с этими бинарными объектами осуществляется в драйвере, в случае php это модуль .so
  • У MongoDB другой интерфйес же, больше пригодный для ORM, а для MySQL вам придется писать уродливую обертку, которая здорово подпортит производительность MySQL. То есть если вы планируете писать запросы рукми — MySQL конечно круче, а если юзаете ORM — то лучше бросайте это бесперспективное дело :)
  • Хороший топик, и некоторые комменты порадовали.
    Но вот в чем приколы (!):

    1. MongoDB не дает ответа insert/update/delete, просто глотает. Чтобы узнать успешна ли операция надо в тот же коннект запульнуть специальный запрос и получить ответ.

    2. На каждый коннект выделяется 1 тред, который по порядку выполняет операции приходящие в этот коннект. Поэтому, для нормального бенчмарка надо хотя сделать кол-во коннектов большим или равным 2*кол-во ядер.

    3. В MongoDB операция insert это фактически thread-safe изменение позиции вставки (чтоб два конкурентных инсерта не перезаписали одну и ту же позицию в файле) и собственно mmap. Ну и конечно задроченное заоптимизированное обновление индекса. Это происходит ну очень быстро, нет смысла сравнивать с MySQL и прочими «сложными» базами данных. Упрётесь в сеть/в диск, никак не в CPU и не в архитектурные блокировки.
    • MongoDB не дает ответа insert/update/delete, просто глотает.
      Если работать через драйвер Python — по умолчанию на insert даёт ответ.
      In [7]: mydb.users.insert({
         ...:     'username': 'test',
         ...:     'password': 'secret'})
      Out[7]: ObjectId('4affa006c8021f0a53000001')

      Разумеется это можно отключить, что даст нехилую прибавку в скорости. 150 000 простых объектов вставляется за 45 секунд. С опцией manipulate=False — за 30.
Только авторизованные пользователи могут оставлять комментарии. Авторизуйтесь, пожалуйста.