MySQL - обзор типов таблиц

mysql

Здравствуйте, сегодня мы поговорим о типах таблиц в MySQL. Архитектура MySQL позволяет подключать разные движки таблиц. На данный момент MySQL поддерживает множество различных типов таблиц, каждый из которых имеет свои преимущества и недостатки. Я перечислю и коротко опишу основные типы таблиц, а затем проведу небольшой тест производительности наиболее часто используемых типов - myisam и innodb.

Для того что-бы посмотреть какие типы поддерживает ваша инсталляция MySQL необходимо выполнить следующий SQL запрос:

SHOW ENGINES;

В результате вы получаете таблицу содержащую информацию о том какие типы таблиц установлены в вашей системе и краткое описание их возможностей.

Engine Support Comment Transactions XA Savepoints
FEDERATED NO Federated MySQL storage engine NULL NULL NULL CSV
MyISAM YES MyISAM storage engine NO NO NO
BLACKHOLE YES /dev/null storage engine (anything you write to it disappears) NO NO NO
MRG_MYISAM YES Collection of identical MyISAM tables NO NO NO
MEMORY YES Hash based, stored in memory, useful for temporary tables NO NO NO
ARCHIVE YES Archive storage engine NO NO NO
InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES
PERFORMANCE_SCHEMA YES Performance Schema NO NO NO

Нас в основном будет интересовать столбец support, который содержит информацию о поддержке типа таблицы и может принимать значения: NO - не поддерживается, YES - поддерживается, DEFAULT -используется по-умолчанию. Начиная с версии 5.5.5 по-умолчанию выбран тип innodb, ранее стандартным типом был myisam.

В версии MySQL 5.5 поддерживается 9 различных типов таблиц.

Сравнительная таблица основных типов таблиц

Функция MyISAM Memory InnoDB Archive
Максимальный объём хранимых данных 256TB RAM 64TB Нет
Транзакции Нет Нет Да Нет
Блокировки Таблица Таблица Запись Запись
MVCC Нет Нет Да Нет
B-деревья Да Да Да Нет
Хэш индексы Нет Да Нет Нет
Индексы полнотекстового поиска Да Нет Нет Нет
Кластерные индексы Нет Нет Да Нет
Кэширование данных Нет Н/д Да Нет
Кэширование индексов Да Н/д Да Нет
Сжатие данных Да Нет Да Да
Шифрование данных Да Да Да Да
Поддержка кластерных БД Нет Нет Нет Нет
Репликация Да Да Да Да
Внешние ключи Нет Нет Да Нет
Бэкап Да Да Да Да
Кэширование запросов Да Да Да Да

Тестирование производительность InnoDB и MyIASM

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

CREATE TABLE `inno` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `data` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE `myisam` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `data` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM;

Напишем небольшой скрипт который будет выполнять 3 теста: запись данных (insert), выборка по ключу, выборка по не ключевому полю.

<?php
// ...
class timer{
    public $value=0;

    public function start(){
        $this->value = microtime(true);
    }

    public function end(){
        return microtime(true) - $this->value;
    }
}

$timer = new timer();

mysql_connect('localhost','root');
mysql_select_db('test');

$data = array();
$select_query = 'SELECT data FROM myisam WHERE id = :val:';
for ($i = 0; $i <= 10000; $i++){
    $result = mysql_query(str_replace(':val:', $i, $select_query));
    $tmp = mysql_fetch_array($result);
    $data[] = $tmp[0];
}

echo '<br/>MyISAM select<br/>';
$select_query = 'SELECT * FROM myisam WHERE data = :val:';
$timer->start();
foreach ($data as $one){
    mysql_query(str_replace(':val:', $one, $select_query));
}
echo $timer->end() . ' s<br/>';

echo '<br/>InnoDB select<br/>';
$select_query = 'SELECT * FROM inno WHERE data = :val:';
$timer->start();
foreach ($data as $one){
    mysql_query(str_replace(':val:', $one, $select_query));
}
echo $timer->end() . ' s<br/>';

/*

$data = array();
for ($i = 0; $i <= 10000; $i++){
    $data[] = mt_rand(0, 100500);
}

echo '<br/>MyISAM select by key<br/>';
$select_query = 'SELECT * FROM myisam WHERE id = :val:';
$timer->start();
for ($i = 0; $i <= 10000; $i++){
    mysql_query(str_replace(':val:', $i, $select_query));
}
echo $timer->end() . ' s<br/>';

echo '<br/>InnoDB select by key<br/>';
$select_query = 'SELECT * FROM inno WHERE id = :val:';
$timer->start();
for ($i = 0; $i <= 10000; $i++){
    mysql_query(str_replace(':val:', $i, $select_query));
}
echo $timer->end() . ' s<br/>';
*/

/*

$data = array();
for ($i = 0; $i <= 10000; $i++){
    $data[] = mt_rand(0, 100500);
}

echo '<br/>MyISAM insert<br/>';
$insert_query = 'INSERT INTO myisam VALUES (NULL,\':val:\')';
$timer->start();
foreach ($data as $one){
    mysql_query(str_replace(':val:', $one, $insert_query));
}
echo $timer->end() . ' s<br/>';

echo 'InnoDB insert<br/>';
$insert_query = 'INSERT INTO inno VALUES (NULL,\':val:\')';
$timer->start();
foreach ($data as $one){
    mysql_query(str_replace(':val:', $one, $insert_query));
}
echo $timer->end() . ' s<br/>';
 */

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

Тест InnoDB MyISAM
Вставка данных(insert) 15.697 с 1.591 с
Выборка по ключу 1.678 с 1.603 с
Выборка по не ключевому полю 149.961 c 95.984 c

Как мы видим myisam работает значительно быстрее, особенно это заметно при вставке данных. Хотя innodb и дает ряд новых возможностей и преимуществ, такая медлительность не позволяет ему конкурировать с myisam, особенно в web-приложениях.