MySQL и скорость выполнения INSERT для разных типов таблиц

Сравнение скорости выполнения INSERT/INSERT DELAYED для таблиц типа HEAP (MEMORY), InnoDB и MyISAM

Я сейчас работаю над очень интересным проектом, который, как надеется заказчик, составит серьёзную конкуренцию Google Analytics. Но речь не об этом. Разбираясь с архитектурой системы, я обнаружил весьма интересную деталь: 8 гигабайт памяти сервера отдается под несколько таблиц типа . Так как HEAP-таблицы хранятся в исключительно в памяти, то операция вставки (INSERT) должна выполняться очень быстро, так как временные затраты, связанные с перемещением головок диска и физической записью, отсутствуют. Я решил найти подтверждение этой теории. Google is your friend, и я довольно быстро нашел статью MySQL Engine INSERT speed.

Меня несколько смутили результаты, приведённые автором:

  • DELAY_KEY_WRITE=ALL): 33 000 INSERT/сек
  • : 24 700 INSERT/сек
  • MEMORY: 64 000 INSERT/сек

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

Первыми возникшими вопросами были:

  1. Какой тип вставки использовался для MyISAM/InnoDB-таблиц — INSERT или INSERT DELAYED?
  2. Каким образом вставлялись данные — построчно или блочно (extended insert)?
  3. Значение AUTOCOMMIT при работе с таблицей InnoDB.

Об этом оставалось только гадать, поэтому я решил повторить этот эксперимент.

Методика эксперимента:
Создаются три таблицы:

[-]
View Code MySQL
CREATE TABLE `test0` (
    `field` INTEGER UNSIGNED NOT NULL
) TYPE=HEAP;

CREATE TABLE `test1` (
    `field` INTEGER UNSIGNED NOT NULL
) TYPE=InnoDB;

CREATE TABLE `test2` (
    `field` INTEGER UNSIGNED NOT NULL
) TYPE=MyISAM DELAY_KEY_WRITE=1;

Перед началом эксперимента выполнялась команда

[-]
View Code MySQL
SET AUTOCOMMIT=0

Затем в цикле в таблицу вставлялись случайно сгенерированные данные (компьютер, на котором проводился эксперимент, был слабый, поэтому я ограничился тридцатью тысячами записями). После цикла выполнялся COMMIT. Скрипт выполнялся 10 раз, бралось среднее время.

Исходный текст скрипта:

[-]
View Code PHP
<?php
    set_time_limit(0);

    function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return (float)$usec + (float)$sec;
    }


    $link = mysql_connect('localhost', 'root', '');
    mysql_select_db('test', $link);

    $schema = "CREATE TABLE `test` (`field` INTEGER UNSIGNED NOT NULL)";
    $engines = array(
        ' TYPE=HEAP',
        ' TYPE=InnoDB',
        ' DELAY_KEY_WRITE = 1 TYPE=MyISAM'
    );

    $inserts = array(
        '',
        '',
        'DELAYED',
    );

    mysql_query("DROP TABLE IF EXISTS `test0`, `test1`, `test2`");
    mysql_query("SET AUTOCOMMIT=0");

    for ($i=0; $i<count($engines); ++$i) {
        $query = preg_replace('/`test`/', "`test{$i}`", $schema) . $engines[$i];
        mysql_query($query);
        mysql_query("COMMIT", $link);

        $start = microtime_float();
        for ($j=0; $j<30000; ++$j) {
            $val = mt_rand();
            mysql_query("INSERT {$inserts[$i]} INTO `test{$i}` (`field`) VALUES({$val})", $link);
        }

        mysql_query("COMMIT", $link);
        $end = microtime_float();
        print $end - $start . "\n";
    }

    mysql_close($link);
?>

У меня получились такие результаты (я привожу относительную — относительно таблиц типа HEAP — скорость):

  HEAP InnoDB MyISAM
INSERT 1.000 1.277 1.162
INSERT DELAYED 2.125 0.998

Эксперимент показал, что разница по скорости между INSERT DELAYED для таблицы MyISAM и INSERT для таблицы HEAP очень незначительна. Таблицы InnoDB действительно оказались медленнее, но не сильно. Большую роль здесь могла сыграть «слабость» тестового компьютера и значение переменной innodb_flush_log_at_trx_commit. Вдобавок, MyISAM был сконфигурирован очень даже хорошо, в то время как InnoDB использовал практически значения по умолчанию (мне редко приходится пользоваться таблицами InnoDB, поэтому тонкой настройкой я не занимался). Тем не менее, результаты проведенного мной эксперимента совсем не согласуются с данными, приведёнными в исходной статье. Кто же из нас прав?

Автор: ; опубликовано в: MySQL, PHP; метки: benchmark, HEAP, InnoDB, MyISAM, speed, storage engine, производительность
20
Мар
2008

RSS Комментарии к статье «MySQL и скорость выполнения INSERT для разных типов таблиц» (4)  »

  1. HEAP InnoDB MyISAM
    INSERT 1.000 1.277 1.162
    INSERT DELAYED 2.125 0.998

    А как эти данные сопоставить с числом запросов, что есть ЕДИНИЦЕЙ в этой таблице??

  2. Я измерял скорость вставки данных относительно скорости выполнения операции INSERT в HEAP-таблицу. То есть все полученные значения делились на значение INSERT(HEAP), и таким образом получались относительные значения.

  3. Тест проведен не объективно. Во первых, функция mt_rand() выполняется достаточно долго, и существенно искажает результаты теста.
    Во вторых, открываем мануал по MySQL (http://www.mysql.ru/docs/man/INSERT_DELAYED.html) и видим
    «INSERT DELAYED работает только с таблицами типа ISAM и MyISAM.», возникаем вопрос зачем это было тестить на HEAP и InnoDB, если эти таблицы этого не поддерживают?

    идем далее..
    mysql_query(«COMMIT», $link)
    зачем?? никаких транзакций здесь не было..

    • Тест проведен не объективно.

      :-)

      Во первых, функция mt_rand() выполняется достаточно долго

      Она выполняется для всех типов таблиц. Соответственно, от неё страдают все три типа таблиц. Поэтому и числа приведены не абсолютные, а относительные.

      INSERT DELAYED работает только с таблицами типа ISAM и MyISAM.

      По крайней мере, с MySQL 5.0 это уже не так:

      INSERT DELAYED works only with MyISAM, MEMORY, and ARCHIVE tables.

      HEAP = MEMORY

      возникаем вопрос зачем это было тестить на HEAP и InnoDB, если эти таблицы этого не поддерживают?

      Вы код посмотрите :-) mysql_query("INSERT {$inserts[$i]} INTO `test{$i}` (`field`) VALUES({$val})", $link);

      DELAYED это $inserts[2], что соответствует таблице MyISAM. Попытка выполнить INSERT DELAYED на InnoDB закончится ошибкой.

      зачем?? никаких транзакций здесь не было..

      Для InnoDB SET autocommit=0; вроде как начинает неявную транзакцию.

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «MySQL и скорость выполнения INSERT для разных типов таблиц»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा