По каким причинам ** НЕ ** используется механизм хранения MEMORY в MySQL?
28
Недавно я обнаружил, что в MySQL есть механизм памяти, о котором я не знал (большая часть моей работы с базами данных предназначена для хобби-проектов, поэтому я узнаю, что мне нужно, по ходу работы). Кажется, что эта опция должна дать мне значительно улучшенную производительность, поэтому мне интересно, есть ли какие-либо недостатки, которые идут с этим. Два из которых я знаю:
Мне нужно иметь достаточно оперативной памяти для хранения таблицы (ов).
Столы теряются, если машина выключается.
Я считаю, что # 1 не должно быть проблемой, так как я использую AWS EC2 и могу перейти к типу экземпляра с большим объемом памяти, если это необходимо. Я считаю, что могу смягчить # 2, сбросив обратно на диск по мере необходимости.
Какие еще проблемы есть? Может ли механизм памяти когда-либо давать худшую производительность, чем MyISAM или InnoDB? Я думаю, что прочитал кое-что, что индексы отличаются с этим двигателем; это то, что мне нужно беспокоиться?
Никакой поддержки транзакций или FK, что означает, что вам придется управлять целостностью транзакций и ссылочной целостностью в вашем собственном коде (что может оказаться гораздо менее эффективным, чем позволить БД сделать это за вас, хотя это очень зависит от вашего приложения). ожидаемые модели поведения).
Только блокировка на уровне таблицы: это может стать серьезным препятствием для масштабируемости, если вашему приложению требуется несколько одновременных устройств записи для одного и того же набора таблиц или в тех случаях, когда ваши операции чтения используют блокировки для обеспечения согласованности чтения данных - в таких случаях таблица на основе диска поддерживает гораздо более тонкую гранулярность блокировки, будет работать намного лучше, если достаточно ее содержимого в настоящее время кэшируется в RAM.
Кроме этого, при условии, что у вас достаточно ОЗУ, таблица на основе памяти должна быть быстрее, чем таблица на основе диска. Очевидно, что необходимо учитывать моментальные снимки на диске, чтобы решить вопрос о том, что происходит при перезагрузке экземпляра сервера, что может полностью свести на нет выигрыш в производительности в целом, если данные нужно часто захватывать (если вы можете потерять день данные в таком случае вы можете просто делать резервную копию один раз в день, но в большинстве случаев это будет неприемлемо).
Альтернативой может быть:
Используйте таблицы на основе дисков, но убедитесь, что у вас более чем достаточно ОЗУ для хранения их всех в ОЗУ в любой момент времени (и «достаточно ОЗУ» может быть больше, чем вы думаете, так как вам необходимо учитывать любые другие процессы на машине, ОС Буферы ввода-вывода / кэш и т. Д.)
Сканирование всего содержимого (все страницы данных и индекса) таблицы при каждом запуске для предварительной загрузки содержимого в память SELECT * FROM <table> ORDER BY <pkey fields>для каждой таблицы, а затем SELECT <indexed fields> FROM <table> ORDER BY <index fields>для каждого индекса
Таким образом, все ваши данные находятся в оперативной памяти, вам нужно беспокоиться только о производительности ввода-вывода для операций записи. Если общий рабочий набор вашего приложения намного меньше, чем вся БД (как это обычно бывает) - в большинстве приложений большинство пользователей будут смотреть только самые последние данные, если это время), возможно, вам лучше быть более избирательным в отношении того, насколько Вы сканируете для предварительной загрузки в память, позволяя остальным быть загружены с диска по требованию.
Зачем вам нужна целостность транзакций для базы данных в памяти? Если питание отключается, вы все равно теряете.
Оса
@osa: предполагая, что он позволяет выполнять параллельный доступ, а не сериализовать все, вам понадобится некоторая форма управления целостностью для этого.
Дэвид Спиллетт
14
Есть множество случаев не использовать механизм хранения памяти - и когда InnoDB будет быстрее. Вам просто нужно подумать о параллелизме, а не тривиальных однопоточных тестах.
Если у вас достаточно большой буферный пул, то InnoDB станет полностью резидентным для операций чтения. Базы данных имеют кеши . Они греются!
Кроме того - не стоит недооценивать значение блокировки на уровне строк и MVCC (читатели не блокируют записи). Это может быть «медленнее», когда записи должны сохраняться на диск. Но, по крайней мере, вы не будете блокировать во время этой операции записи, как если бы вы были в таблице памяти (нет MVCC; блокировка на уровне таблицы).
Это упрощенный ответ. Механизм хранения MEMORY можно настроить, используя меньшие типы данных, явно определяя BTREE как тип индекса и ограничивая объем данных, загружаемых в ОЗУ. Это все еще жизнеспособный вариант для небольших наборов. Есть и другие факторы, такие как агрессивный дисковый ввод-вывод. Смотрите мои сообщения dba.stackexchange.com/questions/6156/… и dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA
На самом деле, я проверил изменение индекса (и даже удаление его полностью), и размер не сильно изменился (включая восстановление таблицы с нуля). ИМХО Mysql делает что-то под капотом, может быть, это какая-то оптимизация или выделение самого большого размера для столбца (например, в varchar).
Магалланес
6
Причина почти наверняка связана с вашим VARCHAR: "MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length."dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html По сути , VARCHAR становится CHAR с механизмом MEMORY.
Matthew1471,
2
Другой недостаток таблиц, основанных на MEMORY, заключается в том, что на них нельзя ссылаться несколько раз в одном запросе. По крайней мере, такое поведение было обнаружено до v5.4. Как и в случае с CTE (начиная с v8.x) нет необходимости использовать промежуточные таблицы на основе mem для сложных процедур.
Согласно руководствам MySQL и MariaDB, BLOB и CLOB (различные типы TEXT) не поддерживаются хранилищем MEMORY. Для наших собственных целей это сделало механизм хранения MEMORY практически бесполезным.
Типы переменной длины, такие как VARCHAR, могут использоваться в таблицах MEMORY. Столбцы BLOB или TEXT не поддерживаются для таблиц MEMORY.
При попытке преобразовать только часть базы данных в хранилище MEMORY я обнаружил, что внешние ключи механизма хранения не поддерживаются. Таким образом, все таблицы, которые должны иметь ссылки на внешние ключи к таблицам, содержащие BLOB / CLOB, также должны относиться к типам хранения не в памяти (по крайней мере, это влияет на дочерние таблицы InnoDB).
Таблицы MEMORY не предназначены для постоянного хранения, особенно для больших подмножеств данных или чего-либо, где хранение является критическим. По моему опыту, их лучшая цель - хранить временные записи во время создания и заполнения временных таблиц во время сложных процедур, что для этой цели выполняется значительно быстрее, чем для большинства других типов таблиц, при условии, что порог ключевого буфера для ядра установлен достаточно высоким, чтобы не вызывать запись на диск. Для этой цели это может работать на порядок быстрее, чем MyISAM или InnoDB, поскольку отсутствует дисковый ввод-вывод, а в случае таблицы, которая инкапсулирована в определенной процедуре, индексирование и отношения не имеют такого большого значения, как они. будет там, где ожидается настойчивость.
В дополнение к предыдущим ответам. прямо из руководства MySQL 5.7:
«Производительность MEMORY ограничена конфликтами, возникающими из-за однопоточного выполнения и накладных расходов на блокировку таблиц при обработке обновлений. Это ограничивает масштабируемость при увеличении нагрузки, особенно для смесей операторов, включающих записи».
... и это очень реальное ограничение. Например: если у вас есть несколько сессий, пытающихся создать хорошие быстрые временные таблицы MEMORY, однопоточность может вызвать серьезное узкое место в производительности.
Есть множество случаев не использовать механизм хранения памяти - и когда InnoDB будет быстрее. Вам просто нужно подумать о параллелизме, а не тривиальных однопоточных тестах.
Если у вас достаточно большой буферный пул, то InnoDB станет полностью резидентным для операций чтения. Базы данных имеют кеши . Они греются!
Кроме того - не стоит недооценивать значение блокировки на уровне строк и MVCC (читатели не блокируют записи). Это может быть «медленнее», когда записи должны сохраняться на диск. Но, по крайней мере, вы не будете блокировать во время этой операции записи, как если бы вы были в таблице памяти (нет MVCC; блокировка на уровне таблицы).
источник
Для записи. Я проверил таблицы Mysql в памяти для хранения некоторой информации. И я проверил APC PHP (APCu) для хранения той же информации.
Для 58000 реестров. (varchar + целое число + дата).
Таблица имеет только один индекс, поэтому я не думаю, что это основной фактор.
Вывод:
Таблица памяти не подходит для «больших» таблиц, потому что она использует слишком много памяти.
источник
"MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length."
dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html По сути , VARCHAR становится CHAR с механизмом MEMORY.Другой недостаток таблиц, основанных на MEMORY, заключается в том, что на них нельзя ссылаться несколько раз в одном запросе. По крайней мере, такое поведение было обнаружено до v5.4. Как и в случае с CTE (начиная с v8.x) нет необходимости использовать промежуточные таблицы на основе mem для сложных процедур.
источник
Согласно руководствам MySQL и MariaDB, BLOB и CLOB (различные типы TEXT) не поддерживаются хранилищем MEMORY. Для наших собственных целей это сделало механизм хранения MEMORY практически бесполезным.
http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html
https://mariadb.com/kb/en/mariadb/memory-storage-engine/
При попытке преобразовать только часть базы данных в хранилище MEMORY я обнаружил, что внешние ключи механизма хранения не поддерживаются. Таким образом, все таблицы, которые должны иметь ссылки на внешние ключи к таблицам, содержащие BLOB / CLOB, также должны относиться к типам хранения не в памяти (по крайней мере, это влияет на дочерние таблицы InnoDB).
источник
Таблицы MEMORY не предназначены для постоянного хранения, особенно для больших подмножеств данных или чего-либо, где хранение является критическим. По моему опыту, их лучшая цель - хранить временные записи во время создания и заполнения временных таблиц во время сложных процедур, что для этой цели выполняется значительно быстрее, чем для большинства других типов таблиц, при условии, что порог ключевого буфера для ядра установлен достаточно высоким, чтобы не вызывать запись на диск. Для этой цели это может работать на порядок быстрее, чем MyISAM или InnoDB, поскольку отсутствует дисковый ввод-вывод, а в случае таблицы, которая инкапсулирована в определенной процедуре, индексирование и отношения не имеют такого большого значения, как они. будет там, где ожидается настойчивость.
источник
В дополнение к предыдущим ответам. прямо из руководства MySQL 5.7:
«Производительность MEMORY ограничена конфликтами, возникающими из-за однопоточного выполнения и накладных расходов на блокировку таблиц при обработке обновлений. Это ограничивает масштабируемость при увеличении нагрузки, особенно для смесей операторов, включающих записи».
... и это очень реальное ограничение. Например: если у вас есть несколько сессий, пытающихся создать хорошие быстрые временные таблицы MEMORY, однопоточность может вызвать серьезное узкое место в производительности.
источник