MySQL проти MongoDB 1000 читає


320

Я був дуже в захваті від MongoDb і останнім часом тестую його. У мене була таблиця з назвою постів в MySQL з приблизно 20 мільйонами записів, індексованими лише в полі під назвою "id".

Я хотів порівняти швидкість з MongoDB, і я провів тест, який отримав би і надрукував 15 записів випадковим чином з наших величезних баз даних. Я виконував запит приблизно в 1000 разів кожен для mysql та MongoDB, і я здивований, що не помічаю великої різниці в швидкості. Можливо, MongoDB у 1,1 рази швидший. Це дуже прикро. Чи є щось, що я роблю неправильно? Я знаю, що мої тести не є ідеальними, але це MySQL нарівні з MongoDb, коли мова йде про читання інтенсивних справ.


Примітка:

  • У мене двоядерний + (2 теми) i7 процесор і 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
Які фактичні часи?
Abe Petrillo

30
Я не DBA, тому це коментар, а не відповідь, але швидкість не повинна бути головною увагою при виборі між MySQL та MongoDB. Такі речі, як схема без схем та схема (тобто, як часто потрібно змінювати схему даних) та масштабування за розміром (тобто, наскільки легко розподілити дані, щоб типовий зчитування вимагає даних лише з одного сервера), є більш важливими для вибору подобається це.
rossdavidh

17
Як можна швидше читати? Він читається з механічного пристрою. Те саме, що і MySQL. Це залежить від швидкості самого пристрою, ви не можете використовувати якусь дивну магію за допомогою коду, щоб пробити межі апаратних засобів.
NB

7
Це питання просто нагадує мені про це: mongodb-is-web-scale.com
oligofren

13
Люди помиляються з тим, що відчувають, ніби поїхали з тим чи іншим. На кухні вам знадобляться як мікрохвильова піч, так і духовка. Ви просто не можете сказати, що я буду використовувати лише те чи інше. Випадки використання для обох систем різні. Якщо вам потрібна ACID для частини вашого додатка, тоді використовуйте RDBMS, якщо не піклується про послідовність та обмеження, і ваші особи можуть зберігатися як усі в одній (колекції), тоді використовуйте MongoDB. Ви в кінцевому підсумку скористаєтеся гібридною системою, ключовим моментом є вирішення, що зберігати де.
Теоман шипахі

Відповіді:


645

MongoDB не магічно швидше. Якщо ви зберігаєте однакові дані, організовані в основному однаковим чином, і отримуєте доступ до них точно так само, то ви дійсно не повинні сподіватися, що ваші результати будуть дещо іншими. Зрештою, MySQL і MongoDB - це GPL, тому, якщо Монго мав у ньому якийсь чарівно кращий код вводу-виводу, то команда MySQL могла би просто включити його у свою кодову базу.

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

Наприклад, розглянемо дизайн, який зберігав багато інформації про складне ціле у нормованому порядку. Це може легко використовувати десятки таблиць у MySQL (або будь-який реляційний db) для зберігання даних у звичайному вигляді з багатьма індексами, необхідними для забезпечення цілісності реляції між таблицями.

Тепер розглянемо таку ж конструкцію з магазином документів. Якщо всі ці пов’язані таблиці підпорядковані головній таблиці (а вони часто є), то, можливо, ви зможете моделювати дані таким чином, що вся сутність зберігається в одному документі. У MongoDB ви можете зберігати це як єдиний документ, в одній колекції. Тут MongoDB починає забезпечувати чудову продуктивність.

У MongoDB, щоб отримати цілу сутність, потрібно виконати:

  • Один пошук індексу в колекції (припускаючи, що сутність отримана за допомогою id)
  • Отримайте вміст однієї сторінки бази даних (фактичний двійковий документ json)

Отже, пошук b-дерева та прочитана двійкова сторінка. Журнал (n) + 1 IO. Якщо індекси можуть повністю перебувати в пам'яті, то 1 IO.

У MySQL з 20 таблицями ви повинні виконати:

  • Один пошук індексу в кореневій таблиці (знову ж таки, припускаючи, що сутність отримана за допомогою id)
  • За допомогою кластерного індексу можна припустити, що значення для кореневого рядка знаходяться в індексі
  • 20+ пошуку діапазону (сподіваємось на індекс) для pk значення сутності
  • Це, ймовірно, не кластеризовані індекси, тому ті самі 20+ пошуку даних, як тільки ми з'ясуємо, які відповідні дочірні рядки.

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

Ці пошукові діапазони, ймовірно, складаються з випадкових вводу-виводу - різні таблиці неодмінно будуть розміщуватися на різних місцях на диску, і можливо, що різні рядки в одному діапазоні в одній таблиці для сутності можуть бути не суміжними (залежно від того, яким чином сутність була оновлено тощо).

Отже, для цього прикладу підсумковий підрахунок приблизно в 20 разів більше IO з MySQL за логічний доступ, порівняно з MongoDB.

Ось як MongoDB може підвищити продуктивність у деяких випадках використання .


43
що робити, якщо ми просто помістимо одну головну таблицю в mysql?
ariso

98
@ariso: Це оптимізація за допомогою денормалізації. Це може забезпечити підвищення продуктивності. Однак якщо ви це зробите, то ви викидаєте чисту конструкцію та всю потужність (не кажучи вже про більшість функцій) реляційної бази даних. І це дійсно працює, поки ви не досягнете межі стовпця.
Шон Рейлі

7
@SeanReilly Ваш приклад із сутностями (має бути відредаговано об’єктами, програмування, орієнтоване на сутність, не існує :)) недійсний. Як сказано в ariso, ви можете серіалізувати об'єкт і зберігати його в db і деріаріалізувати, коли це потрібно (будь-яка форма серіалізації). Справжня сила об'єктів, що зберігаються, зберігається в системах oodbms, не документальних мережах db. Але я погоджуюся з тим, що кожен має своє призначення та сили (але ваш приклад більше вражає бачення та актуальність цієї теми).
Гео С.

9
20 приєднань, я б сказав, це, швидше за все, не найкращий запит на найкращій схемі бази даних, що це могло бути.
Аудрій Меськаускас

8
@SeanReilly Я вважаю ваш приклад дуже корисним. Ви можете створити спеціальний інтерфейс для MySQL, який автоматично серіалізує та десеріалізує об'єкти в таблиці та поводить себе так, як робить mongodb. Але тоді, чому б не просто використати щось спеціально розроблене, щоб використовуватись таким чином? Також ваше використання "сутності" має сенс. Справа в тому, що ви організовуєте дані як документи, а не як поля в таблиці. Незалежно від того, чи документ є об’єктом, складеним мовою ОО, це не має значення для прикладу.
BHS

57

Чи є у вас паралельність, тобто одночасні користувачі? Якщо ви просто запустите запит 1000 разів прямо, лише однією ниткою, різниці майже не буде. Занадто просто для цих двигунів :)

Але я наполегливо пропоную вам створити справжній сеанс тестування навантаження, що означає використання інжектора, такого як JMeter з 10, 20 або 50 користувачами В ОДНІЙ ЧАС, щоб ви дійсно побачили різницю (спробуйте вставити цей код у веб-сторінку JMeter може запитувати).

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

Це дійсно має бути частиною вашого тесту: паралельність та двигун MySQL. Тоді, дані / схема проектування та потреби в застосуванні, звичайно, є величезними вимогами, поза часом реагування. Повідомте мене, коли ви отримаєте результати, я також потребую інформації про це!


42
Чи можете ви поділитися своїми результатами?
Імран Омар Бухш

1
Я, результати з цього стануть дуже корисними
Василь Попов

3
Звичайно, це було б просто масштабно ... якби це були яблука до яблук, як вони говорили в іншій частині цієї теми. Отже, якщо він на avg виконує x, тепер симулюйте з декількох джерел, будь ласка, поясніть, чому mongo був би швидшим. тобто дозвольмо просто сказати заради домовленості, що mysql був на avg швидше за один запит ... чому монго зараз стане швидшим для кількох? Я не вважаю це дуже науковим. Я кажу, що тест дійсний .. але не настільки впевнений, наскільки різниця була б величезною, якби ви порівнювали яблука з яблуками, як решта пояснює тему.
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)

91
15 хв., Щоб вставити 10000 рядків? Це дуже анемічна база даних MySQL. З мого досвіду, якщо така операція триває 1 секунду, мій телефон загоряється скаргами. :)
Мордехай

1
Xtreme Biker дивіться за посиланням. Я розмістив тест від інших людей з іншими налаштуваннями.
користувач2081518

14
Кілька пунктів: 1) Mysql потрібно оптимізувати та налаштувати належним чином, існує багато різних способів вставити великі обсяги даних, і при правильному виконанні це може зайняти 0,1% 15min, див. Цю сторінку, наприклад. 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% швидшим для основного запиту, позбавленого джазу.

урххх.


4
звичайно, практика кодування може мати велику різницю в будь-якій ситуації, але це не характерно для будь-якого типу мови, api чи розширення. генерація випадкових чисел перед запуском таймера призведе до зміни, але більшість часу в процесі не викликає сумнівів у транзакціях із базою даних. Генерація випадкових чисел є тривіальною, бази даних SQL і NoSQL не є.
JSON

1
не вибирайте номер rand. явно ви пропускали створення з'єднання кожного разу. усі питання додаються до тестування чогось іншого, ніж призначено.
Габе Веселка

2
Ні, не сумував. MySQL не зможе закрити з'єднання, поки скрипт не закінчиться, якщо не буде викликано mysqli_close (). В іншому випадку повторні виклики до mysqli_connect () будуть лише витягувати існуючий ресурс mysql з поточної таблиці ресурсів, а не здійснювати нову процедуру підключення. Я не зовсім впевнений, що таке об'єкт AQLDatabase, але якщо він використовує mysql lib (що, швидше за все, це робити), він матиме таку саму поведінку. Розширення MongoDB використовує об'єднання з'єднань, тому те саме основне відбувається при створенні mongodb 'з'єднання' більше одного разу в сценарії.
JSON

Я погоджуюся, що його тест міг бути зроблений інакше, але він відображає ті ж основні результати, що й інші лавки MySQL проти Mongo, які я бачив. Монго, як правило, швидше під час вставки (набагато швидше для більш простих вставок), а MySQL, як правило, швидше при виборі.
JSON

зізнаюся, я був надто похмурий; саме той html-рядковий конмат "<br>" насправді "підштовхнув" мене. вам не потрібен гарний друк у тестах. навіть ітерація здається тестом php, а не тестом бази даних. загалом, що AQLDatabase 'можливо / можливо' момент ... більше інгредієнтів означає більше невідомих.
Гейб Веселка

17

https://github.com/reoxey/benchmark

орієнтир

порівняння швидкості MySQL та MongoDB в GOLANG1.6 та PHP5

система, яка використовується для орієнтиру: DELL CPU i5 4-го покоління 1,70 ГГц * 4 ОЗ 4 ГБ GPU, оперативної пам’яті 2 ГБ

Порівняння швидкості RDBMS та NoSQL для INSERT, SELECT, UPDATE, DELETE, виконуючи різну кількість рядків 10,100,1000,10000,100000,1000000

Мова, яка використовується для виконання: PHP5 та найшвидша мова 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

myisam не є innodb, також яка версія версії та двигуна mongodb?

1
важливо вказати версії MySQL та MongoDB.
Мирон

1
Не використовуйте MyISAM. Використовуйте пакетні вставки!
Рік Джеймс

MySQL швидше, ніж Mongodb в Insert query ?! це здається неправдою, поки mysql не потрібно підготувати стовпчики та взаємовідносини. mysql select швидше, ніж mongodb select, але вставте запит, mongo - швидше
Exind

6

Ось невелике дослідження, яке досліджувало RDBMS проти NoSQL за допомогою MySQL проти Mongo, висновки були узгоджені з відповіддю @Sean Reilly. Коротше кажучи, вигода приносить дизайн, а не деяка різниця в швидкості. Висновок на сторінці 35-36:

RDBMS vs NoSQL: Порівняння продуктивності та масштабування

Проект протестував, проаналізував та порівняв ефективність та масштабованість двох типів баз даних. Проведені експерименти включали виконання різних номерів і типів запитів, деякі складніші за інші, щоб проаналізувати, як масштабування баз даних збільшується. Найважливішим фактором у цьому випадку став тип запиту, який використовувався, оскільки MongoDB міг швидше обробляти складніші запити, в основному завдяки своїй більш простої схемі при жертві дублювання даних, що означає, що база даних NoSQL може містити велику кількість дублікатів даних. Хоча схема, безпосередньо перенесена з RDBMS, може бути використана, це усуне перевагу базового представлення даних MongoDB для субдокументів, що дозволило використовувати менше запитів до бази даних, оскільки таблиці були об'єднані.Незважаючи на підвищення продуктивності, який мав MongoDB над MySQL в цих складних запитах, коли еталон моделював MySQL-запит аналогічно складному запиту MongoDB, використовуючи вкладені SELECT, MySQL найкраще працював, хоча при більшій кількості з'єднань вони поводилися однаково. Останній тип запиту, орієнтованим на який був складний запит, що містить два JOINS та підзапрос, показав перевагу, яку має MongoDB над MySQL завдяки використанню піддокументів. Ця перевага полягає в ціні дублювання даних, що призводить до збільшення розміру бази даних. Якщо такі запити є типовими для програми, важливо розглянути бази даних NoSQL як альтернативні, враховуючи витрати на зберігання та розмір пам’яті внаслідок збільшення розміру бази даних.


-6

На одному сервері MongoDb не буде швидшим, ніж mysql MyISAM як для читання, так і для запису, якщо розміри таблиці / документа невеликі від 1 ГБ до 20 ГБ.
MonoDB буде швидше при паралельному зменшенні на кластерах з декількома вузлами, де Mysql НЕ МОЖЕТЕ масштабувати горизонтально.


5
Чи можете ви надати якісь докази чи більше деталей, щоб підтвердити це?
Стів Вестбрук

Не можете масштабувати горизонтально? Що з НДБ? DRBD підтримував MySQL?
Ернестас

Це не правда. У MongoDB ліміт документів 16МД. Mysql може мати набагато більше, якщо вам подобається
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.