2016-06-06 5 views
0

Есть несколько Q & A для «Почему InnoDB (намного) медленнее, чем MyISAM», но я не мог найти ни одной темы для обратного.Почему myisam медленнее, чем Innodb

Итак, у меня была таблица, определяемая как InnoDB, где я хранил содержимое файла в поле blob. Поскольку обычно для этого MyISAM следует использовать, я переключил эту таблицу. Вот его структура:

CREATE TABLE `liv_fx_files_files` (
    `fid` int(11) NOT NULL AUTO_INCREMENT, 
    `filedata` longblob NOT NULL, 
    `filetype` varchar(255) NOT NULL, 
    `filename` varchar(255) NOT NULL, 
    `filesize` int(11) NOT NULL, 
    `context` varchar(1) NOT NULL DEFAULT '', 
    `saveuser` varchar(32) NOT NULL, 
    `savetime` int(11) NOT NULL, 
    `_state` int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`fid`), 
    KEY `_state` (`_state`) 
) ENGINE=MyISAM AUTO_INCREMENT=4550 DEFAULT CHARSET=utf8; 

Есть 4549 записи, хранящиеся в нем до сих пор (с filedata происходит от 0 до 48м Сумма всех файлов составляет около 6G

Поэтому, когда мне нужно знать текущий итог.. Filesize я выполняю запрос

SELECT SUM(filesize) FROM liv_fx_files_files; 

проблема заключается в том, что, так как я перешел с InnoDB в MyISAM этот простой запрос длится очень долго (около 30 секунд и больше), тогда как на InnoDB это было сделано в рамках одной секунды.

Но агрегации - это не единственные запросы, которые очень медленны; это почти каждый запрос.

Я думаю, я мог бы исправить это, приняв конфигурацию (которая в настоящее время оптимизирована для использования только InnoDB), но не знает, какие настройки нужно настроить. Кто-нибудь подскажет мне, пожалуйста?

current mysql server config (SHOW VARIABLES as csv)

Пример для другого запроса обожженной на обоих типов таблиц (оба содержат точные же данные, и имеют такое же определение). Все остальные проверенные запросы ведут себя одинаково, скажем, намного быстрее работают с таблицей MyISAM в виде InnoDB!

SELECT sql_no_cache `fxfilefile`.`filename` AS `filename` FROM `myisamtable`|`innodbtable` AS `fxfilefile` WHERE `fxfilefile`.`filename` LIKE '%foo%'; 
+1

Опубликовать текущий файл конфигурации, возможно, вы используете очень небольшую конфигурацию. Также рассмотрите добавление индекса в поле filesize. – Ghigo

+0

@Ghigo спасибо, добавив, что индекс решает проблему скорости с агрегацией этого столбца, но не улучшает скорость для других запросов. Файл конфигурации добавлен – toshniba

+0

Это не очень помогает: для таблиц MyISAM кэширование обрабатывается базовой ОС. Пространство, доступное для этого, не видно изнутри MySQL. – symcbean

ответ

2

Резюме: Используйте InnoDB и соответствующим образом измените настройки my.cnf.

Детали:

"MyISAM быстрее" - это сказка для престарелых жен. Сегодня, InnoDB быстрее в наиболее ситуаций.

Если у вас есть по крайней мере, 4 Гб оперативной памяти ...

  • Если все-MyISAM, key_buffer_size должна быть около 20% оперативной памяти; innodb_buffer_pool_size должно быть 0.
  • Если все-InnoDB, key_buffer_size должно быть, скажем, всего 20 МБ; innodb_buffer_pool_size должно быть около 70% ОЗУ.
  • Если смесь, сделайте что-то среднее между ними. More discussion.

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

  • MyISAM помещает весь BLOB 'inline' в другие столбцы.
  • InnoDB ставит большинство или всех блоков в другие блоки.

Вывод:
сканирование таблицы в таблицу MyISAM тратит много времени перешагивая коровы пэддис; InnoDB намного быстрее если вы не трогаете BLOB.
Это делает InnoDB явным победителем для SELECT SUM(x) FROM tbl;, когда нет индекса на x. С INDEX(x), любой двигатель будет быстрым.

Из-за того, что BLOB является встроенным, MyISAM имеет проблемы с фрагментацией, если вы обновляете записи в таблице; У InnoDB гораздо меньше фрагментации. Это влияет на все операции, что делает InnoDB победителем снова.

Порядок столбцов в CREATE TABLE не влияет на производительность в любом двигателе.

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

Если вы решите пойти с MyISAM, я бы рекомендовал «параллельную» таблицу («вертикальное разбиение»). Поместите BLOB и id в отдельную таблицу. Это поможет MyISAM приблизиться к модели и производительности InnoDB, но добавит сложности к вашему коду.

Для «точечных запросов» (поиск одной строки с помощью индекса) не будет большой разницы в производительности между двигателями.

Ваш my.cnf кажется антикварным; set-variable не требуется в течение длительного времени.

0

Попробуйте изменить конфигурационный файл MySQL, как правило, /etc/mysql/my.cnf и использовать «огромный» пресет.

# The MySQL server 
[mysqld] 
port  = 3306 
socket  = /var/run/mysqld/mysqld.sock 
skip-locking 
set-variable = key_buffer=384M 
set-variable = max_allowed_packet=1M 
set-variable = table_cache=512 
set-variable = sort_buffer=2M 
set-variable = record_buffer=2M 
set-variable = thread_cache=8 
# Try number of CPU's*2 for thread_concurrency 
set-variable = thread_concurrency=8 
set-variable = myisam_sort_buffer_size=64M 
+0

Спасибо за это предложение, но большинство из этих переменных устарели. Поэтому я заменил их текущими именами (и полностью удалил thread_concurrency, как и для более старых соляриев), но запросы не ускорялись. – toshniba

+0

Укажите, какую версию MySQL вы используете, оперативную систему, серверное оборудование. Похоже, у вас есть некоторые проблемы. Я выполняю запросы с 300 КБ записей на MyISAM в 500 мс. – Ghigo

+0

Как MyISAM доступ к OS/HDD, кроме InnoDB? Это openSUSE Leap 42.1 (x86_64) с mysql 5.6.28 (устанавливается zypper) – toshniba

0

Конечно, 30 секунд для чтения 4500 записей происходит очень медленно. Предполагая, что есть много места для кэширования ввода-вывода, первое, что я попробую, это изменить порядок полей; если они записаны в таблицу в том порядке, в котором они объявлены, СУБД необходимо будет искать до конца каждой записи перед чтением значения размера (я бы также рекомендовал ограничить размер этих столбцов vharchar (255), и что varhar (1) NOT NULL должен быть CHAR).

CREATE TABLE `liv_fx_files_files2` (
    `fid` int(11) NOT NULL AUTO_INCREMENT, 
    `filesize` int(11) NOT NULL, 
    `context` char(1) NOT NULL DEFAULT '', 
    `saveuser` varchar(32) NOT NULL, 
    `savetime` int(11) NOT NULL, 
    `_state` int(11) NOT NULL DEFAULT '0', 
    `filetype` varchar(255) NOT NULL, 
    `filename` varchar(255) NOT NULL, 
    `filedata` longblob NOT NULL, 
    PRIMARY KEY (`fid`), 
    KEY `_state` (`_state`) 
) ENGINE=MyISAM AUTO_INCREMENT=4550 DEFAULT CHARSET=utf8; 

INSERT INTO liv_fx_files_files2 
(fid, filesize, context, saveuser, savetime, _state, filetype, filename, filedata) 
SELECT fid, filesize, context, saveuser, savetime, _state, filetype, filename, filedata 
FROM liv_fx_files_files; 

Но в идеале я бы разделил данные и метаданные на отдельные таблицы.

+0

спасибо за ваш вклад. Хороший подход к изменению порядка столбцов, но, к сожалению, не имел никакого эффекта. Принятые определения столбцов уже были запланированы для следующих шагов, а также для разделения таблицы. Я думаю, что это почти что-то вроде конфига, возможно, узкое место в любом буфере, но я не знаком с MyISAM, но кажется, что сервер mysql настроен так плохо. Почему, черт возьми, MyISAM намного медленнее, чем InnoDB ??!? – toshniba