MySQL против MongoDB 1000 читает

321

Я был очень взволнован по поводу MongoDb и тестировал его в последнее время. У меня была таблица с именем posts в MySQL, и около 20 миллионов записей были проиндексированы только в поле с именем id.

Я хотел сравнить скорость с MongoDB, и я провел тест, который получит и распечатает 15 записей случайным образом из наших огромных баз данных. Я выполнял запрос около 1000 раз каждый для mysql и MongoDB, и я удивлен, что не замечаю большой разницы в скорости. Возможно MongoDB в 1,1 раза быстрее. Это очень разочаровывает. Есть ли что-то, что я делаю не так? Я знаю, что мои тесты не идеальны, но MySQL наравне с MongoDb, когда дело доходит до интенсивной работы по чтению.


Примечание:

  • У меня есть два ядра + (2 потока) i7 CPU и 4 ГБ оперативной памяти
  • У меня есть 20 разделов на MySQL каждый из 1 миллиона записей

Пример кода, используемого для тестирования MongoDB

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$time_taken = 0;
$tries = 100;
// connect
$time_start = microtime_float();

for($i=1;$i<=$tries;$i++)
{
    $m = new Mongo();
    $db = $m->swalif;
    $cursor = $db->posts->find(array('id' => array('$in' => get_15_random_numbers())));
    foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }
}

$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

?>


Пример кода для тестирования MySQL

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$BASE_PATH = "../src/";
include_once($BASE_PATH  . "classes/forumdb.php");

$time_taken = 0;
$tries = 100;
$time_start = microtime_float();
for($i=1;$i<=$tries;$i++)
{
    $db = new AQLDatabase();
    $sql = "select * from posts_really_big where id in (".implode(',',get_15_random_numbers()).")";
    $result = $db->executeSQL($sql);
    while ($row = mysql_fetch_array($result) )
    {
        //echo $row["thread_title"] . "<br><Br>";
    }
}
$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000);

    }
    return $numbers;
}
?>
Имран Омар Бухш
источник
11
Каковы фактические времена?
Абэ Петрильо
30
Я не администратор, поэтому это комментарий, а не ответ, но скорость не должна быть основным фактором при выборе между MySQL и MongoDB. Такие вещи, как схема без схемы (т. Е. Как часто нужно менять схему данных) и масштабирование по размеру (т. Е. Насколько легко защитить данные, чтобы при обычном чтении требовались данные только с одного сервера), более важны для выбора как это.
Россдавид
17
Как это может быть быстрее при чтении? Он читает с механического устройства. Так же, как MySQL. Это зависит от скорости самого устройства, вы не можете использовать какое-то странное волшебство с помощью кода, чтобы выйти за пределы аппаратного обеспечения.
NB
7
Этот вопрос только напоминает мне об этом: mongodb-is-web-scale.com
oligofren
13
Люди ошибаются, что им кажется, что они пойдут с тем или другим. Вам понадобится как микроволновая печь, так и духовка на вашей кухне. Вы просто не можете сказать, что я буду использовать только одно или другое. Варианты использования для обеих систем разные. Если вам требуется ACID для части вашего приложения, используйте RDBMS, если вам не нужны согласованность и ограничения, и ваши объекты могут храниться как все в одном (коллекции), тогда используйте MongoDB. В конечном итоге вы будете использовать гибридную систему, ключевым моментом будет решение, что и где хранить.
Теоман Шипахи

Ответы:

647

MongoDB не магически быстрее. Если вы храните одни и те же данные, организованные в основном одинаковым образом, и получаете к ним одинаковый доступ, тогда вы не должны ожидать, что ваши результаты будут сильно отличаться. В конце концов, MySQL и MongoDB оба являются GPL, поэтому, если в Mongo был какой-то магически лучший код ввода-вывода, команда MySQL могла бы просто включить его в свою кодовую базу.

Люди видят производительность MongoDB в реальном мире в основном потому, что MongoDB позволяет вам делать запросы другим способом, который более чувствителен к вашей рабочей нагрузке.

Например, рассмотрим дизайн, который сохранил много информации о сложном объекте в нормализованном порядке. Это может легко использовать десятки таблиц в MySQL (или любой реляционной базе данных) для хранения данных в нормальной форме со многими индексами, необходимыми для обеспечения реляционной целостности между таблицами.

Теперь рассмотрим тот же дизайн с хранилищем документов. Если все эти связанные таблицы подчинены основной таблице (а они часто бывают), вы можете смоделировать данные таким образом, чтобы вся сущность сохранялась в одном документе. В MongoDB вы можете хранить это как один документ, в одной коллекции. Именно здесь MongoDB начинает обеспечивать превосходную производительность.

В MongoDB, чтобы получить всю сущность, вы должны выполнить:

  • Один просмотр индекса для коллекции (при условии, что объект извлекается по id)
  • Получить содержимое одной страницы базы данных (фактический двоичный документ json)

Итак, поиск b-дерева и чтение двоичной страницы. Log (n) + 1 IO. Если индексы могут постоянно находиться в памяти, то 1 IO.

В MySQL с 20 таблицами вы должны выполнить:

  • Один просмотр индекса для корневой таблицы (опять-таки, при условии, что сущность выбирается по id)
  • С кластеризованным индексом мы можем предположить, что значения для корневой строки находятся в индексе
  • Более 20 поисков по диапазону (возможно, по индексу) для значения pk объекта
  • Вероятно, это не кластеризованные индексы, поэтому те же самые 20 и более просмотров данных, когда мы выясним, какие уместные дочерние строки.

Таким образом, общая сумма для mysql, даже если предположить, что все индексы находятся в памяти (что сложнее, поскольку их в 20 раз больше), составляет около 20 поисков по диапазонам.

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

Таким образом, для этого примера итоговый подсчет примерно в 20 раз больше ввода-вывода с MySQL на логический доступ по сравнению с MongoDB.

Именно так MongoDB может повысить производительность в некоторых случаях .

Шон Рейли
источник
43
что если мы просто поместим одну главную таблицу в mysql?
ariso
99
@ariso: это оптимизация путем денормализации. Это может обеспечить повышение производительности. Однако, если вы сделаете это, то вы отбросите свой чистый дизайн и всю мощь (не говоря уже о большинстве функций) реляционной базы данных. И это действительно работает, пока вы не достигнете предела столбца.
Шон Рейли
7
@SeanReilly Ваш пример с сущностями (должен быть отредактирован с объектами, нет объектно-ориентированного программирования :)) неверен. Как сказал Ariso, вы можете сериализовать объект и сохранить его в БД и десериализовать при необходимости (любая форма сериализации). Истинная сила сохраняющихся объектов заключается в системах oodbms, а не в dbumnet db. Но я согласен, что у каждого есть своя собственная цель и сильные стороны (но ваш пример больше запутывает видение и актуальность этой темы).
Geo C.
9
20 объединений, я бы сказал, скорее всего, не самый лучший запрос в наилучшей схеме базы данных.
Аудрюс Мескаускас
8
@SeanReilly Я нашел ваш пример очень полезным. Вы можете создать специальный интерфейс для MySQL, который автоматически сериализует и десериализует объекты в таблицы и ведет себя так, как это делает mongodb. Но тогда почему бы просто не использовать что-то специально разработанное для такого использования? Также ваше использование «сущности» имеет смысл. Дело в том, что вы организуете данные как документы, а не как поля в таблице. Является ли документ объектом, составленным на языке ОО, или нет, это не имеет значения для примера.
BHS
57

Есть ли у вас параллелизм, то есть одновременные пользователи? Если вы просто выполните 1000 раз подряд запрос с одним потоком, разницы почти не будет. Слишком просто для этих двигателей :)

НО я настоятельно рекомендую вам создать настоящий сеанс нагрузочного тестирования, что означает использование инжектора, такого как JMeter, с 10, 20 или 50 пользователями ОДНОВРЕМЕННО, чтобы вы могли реально увидеть разницу (попробуйте встроить этот код в веб-страницу JMeter можно запросить).

Я только что сделал это сегодня на одном сервере (и простой коллекции / таблице), и результаты довольно интересны и удивительны (MongoDb был действительно быстрее при записи и чтении, по сравнению с движком MyISAM и движком InnoDb).

Это действительно должно быть частью вашего теста: параллелизм и движок MySQL. Кроме того, требования к дизайну данных / схемы и приложениям - это, конечно, огромные требования, помимо времени отклика. Дайте мне знать, когда вы получите результаты, я также нуждаюсь в информации об этом!

theAndroid
источник
42
Можете ли вы поделиться своими результатами?
Имран Омар Бухш
1
Я, результаты по этому вопросу будут очень полезны
Василь Попов
3
Конечно, это было бы просто масштабироваться ... если бы это были «Яблоки с яблоками», как они говорили в оставшейся части этой темы. Так что если он на avg выполняет x, теперь симулируйте из нескольких источников, пожалуйста, объясните, почему mongo будет быстрее. т. е. для соглашения просто скажем, что mysql был на avg быстрее для одного запроса ... почему mongo теперь стал быстрее для нескольких? Я не считаю это очень научным. Я говорю, что тест действителен ... но не уверен, насколько велика будет разница, если вы сравниваете яблоки с яблоками, как объясняет остальная часть темы.
Seabizkit
35

Источник: https://github.com/webcaetano/mongo-mysql

10 рядов

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100 рядов

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000 строк

mysql insert: 94813ms (1.58 minutes)
mysql select: 13ms

mongo insert: 1013ms
mongo select: 677ms

10.000 строк

mysql insert: 924695ms (15.41 minutes)
mysql select: 144ms

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)
user2081518
источник
91
15 минут, чтобы вставить 10000 строк? Это очень анемичная база данных MySQL. По моему опыту, если такая операция длится 1 с, мой телефон загорается с жалобами. :)
Мордехай
1
Xtreme Biker взгляните на ссылку. Я отправил тест от других людей с другими настройками.
user2081518
14
Несколько моментов: 1) Mysql необходимо оптимизировать и правильно настроить, есть много разных способов вставки больших объемов данных, и при правильном выполнении это может занять 0,1% от 15 минут, см. Эту страницу, например. 2) MongoDB не сразу записывает данные на диск, поэтому он «выглядит» быстрее, но если ваш компьютер дает сбой, данные теряются. 3) Чтение намного быстрее в MySQL
elipoultorak
81
15 минут на 10.000 строк? Вы набрали каждый ряд? =))))
Юрий
7
любой, кто считает, что для вставки десяти строк в mysql требуется 1,7 секунды, заслуживает боль, которую они получают от монго
Джон
20

мужчина ,,, ответ в том, что вы в основном тестируете PHP, а не базу данных.

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

   foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }

в то время как другой кусок тратит на сбор кучу рандов.

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

тогда есть большая разница ч / б взрыва и в.

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

$m = new Mongo();

против

$db = new AQLDatabase();

так что ваш 101% быстрее может оказаться на 1000% быстрее для основного запроса, лишенного джаза.

urghhh.

Гейб Рейнбоу
источник
4
Естественно, практика кодирования может иметь большое значение в любой ситуации, но это не характерно для любого типа языка, API или расширения. генерация случайных чисел перед запуском таймера будет иметь значение, но большую часть времени в этом процессе, несомненно, составляют транзакции базы данных. генерация случайных чисел тривиальна, а базы данных SQL и NoSQL - нет.
JSON
1
не выбирайте номер ранда. очевидно, вы пропустили создание соединения каждый раз. все проблемы сводятся к тестированию чего-то другого, чем предполагалось
Гейб Рейнбоу
2
Нет, не пропустил это. MySQL не будет закрывать соединение, пока сценарий не завершится, если не будет вызвана mysqli_close (). В противном случае повторные вызовы mysqli_connect () будут только извлекать существующий ресурс mysql из текущей таблицы ресурсов, а не фиксировать новую процедуру подключения. Я не совсем уверен, что такое объект AQLDatabase, но если он использует библиотеку mysql (что, скорее всего, и делает), он будет вести себя так же. Расширение MongoDB использует пул соединений, поэтому при создании mongodb-соединения в сценарии происходит то же самое.
JSON
Я согласен, что его тест мог бы быть сделан по-другому, но он отражает те же основные результаты, что и другие тесты MySQL против Mongo, которые я видел. Mongo обычно быстрее при вставке (намного быстрее для более простых вставок), а MySQL обычно быстрее при выборе.
JSON
по общему признанию, я был слишком уныл; именно эта строка конкатенации html «<br>» действительно «вызвала» меня. вам не нужна красивая печать в тестах. даже повторение похоже на тест php, а не тест базы данных. в целом, тот момент AQLDatabase «возможно / возможно» ... больше ингредиентов означает больше неизвестных.
Гейб Радуга
17

https://github.com/reoxey/benchmark

эталонный тест

сравнение скорости MySQL и MongoDB в GOLANG1.6 и PHP5

система, используемая для тестирования: процессор DELL i5 4-го поколения 1,70 ГГц * 4 оперативных памяти 4 ГБ оперативная память графического процессора 2 ГБ

Сравнение скорости СУБД с NoSQL для INSERT, SELECT, UPDATE, DELETE, выполняющих различное количество строк 10 100 000 000 100 000 100 000 100 000

Используемый язык: PHP5 и Google самый быстрый язык GO 1.6

________________________________________________
GOLANG with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      1.195444ms
100                     6.075053ms
1000                    47.439699ms
10000                   483.999809ms
100000                  4.707089053s
1000000                 49.067407174s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 872.709µs


        SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 20.717354746s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 2.309209968s
100000                  257.411502ms
10000                   26.73954ms
1000                    3.483926ms
100                     915.17µs
10                      650.166µs


            DELETE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 6.065949ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


________________________________________________
GOLANG with MongoDB
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      2.067094ms
100                     8.841597ms
1000                    106.491732ms
10000                   998.225023ms
100000                  8.98172825s
1000000                 1m 29.63203158s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 5.251337439s


        FIND & DISPLAY (with index declared)
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 21.540603252s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1                       1.330954ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 10                     0.0040680000000001s
 100                    0.011595s
 1000                   0.049718s
 10000                  0.457164s
 100000                 4s
 1000000                42s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 1000000                <1s


            SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
  1000000               20s
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MongoDB 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      0.065744s
100                     0.190966s
1000                    0.2163s
10000                   1s
100000                  8s
1000000                 78s


            FIND
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 <1s


            FIND & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 7s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 9s
Reoxey
источник
myisam не innodb, а также какая версия mongodb и механизм хранения?
1
важно указать версии MySQL и MongoDB.
Мирон
1
Не используйте MyISAM. Используйте пакетные вставки!
Рик Джеймс
MySQL быстрее, чем Mongodb в запросе вставки ?! это кажется неправдой, пока mysql не должен подготовить столбцы и взаимосвязи. mysql select быстрее, чем mongodb select, но в запросе на вставку mongo работает быстрее
Exind
6

Вот небольшое исследование, в котором исследовались СУБД и NoSQL с использованием MySQL против Mongo, выводы были в соответствии с ответом @Sean Reilly. Короче говоря, выгода от дизайна, а не от некоторой необработанной разницы в скорости. Заключение на стр. 35-36:

СУБД и NoSQL: сравнение производительности и масштабирования

Проект протестировал, проанализировал и сравнил производительность и масштабируемость двух типов баз данных. Проведенные эксперименты включали выполнение разных номеров и типов запросов, некоторые из которых были более сложными, чем другие, для анализа масштабирования баз данных с увеличением нагрузки. Наиболее важным фактором в этом случае был тип запроса, который использовался, поскольку MongoDB мог обрабатывать более сложные запросы быстрее, в основном благодаря своей более простой схеме, жертвуя дублированием данных, что означает, что база данных NoSQL может содержать большое количество дубликатов данных. Хотя можно было использовать схему, непосредственно перенесенную из RDBMS, это исключило бы преимущество основного представления данных MongoDB для вложенных документов, что позволило использовать меньше запросов к базе данных при объединении таблиц.Несмотря на выигрыш в производительности, который MongoDB имел по сравнению с MySQL в этих сложных запросах, когда эталонный тест моделировал запрос MySQL аналогично сложному запросу MongoDB, используя вложенные SELECT, MySQL работал лучше, хотя при большем количестве соединений они вели себя одинаково. Последний тип сравнительного теста, который представлял собой сложный запрос, содержащий два JOINS и подзапрос, показал преимущество MongoDB над MySQL благодаря использованию вложенных документов. Это преимущество достигается за счет дублирования данных, что приводит к увеличению размера базы данных. Если такие запросы типичны для приложения, то важно рассматривать базы данных NoSQL в качестве альтернативы, принимая во внимание затраты на хранение и объем памяти, возникающие в результате увеличения размера базы данных.

Джейсон Хитчингс
источник
-6

На одном сервере MongoDb не будет работать быстрее MyISAM MySQL в режиме чтения и записи, учитывая, что размеры таблиц / документов малы - от 1 до 20 ГБ.
MonoDB будет быстрее при параллельном уменьшении в кластерах с несколькими узлами, где Mysql НЕ может масштабироваться горизонтально.

чжуомин чэнь
источник
5
Можете ли вы предоставить некоторые доказательства или более подробную информацию, подтверждающую это?
Стив Уэстбрук
Не может масштабироваться горизонтально? Как насчет NDB? DRBD поддержал MySQL?
Эрнестас
Это неправда. MongoDB имеет ограничение в 16MD документов. Mysql может иметь гораздо больше, если хотите