Які причини ** НЕ ** для використання двигуна пам’яті MEMORY в MySQL?


28

Нещодавно я виявив, що в MySQL є двигун "пам'яті", про який я не знав (більшість моєї роботи з базою даних - це для хобі-проектів, тому я дізнаюся, що мені потрібно, коли я йду). Здається, що цей варіант повинен дати мені кардинально покращити продуктивність, тому мені цікаво, чи є якісь недоліки, які пов'язані з цим. Я знаю два:

  1. Мені потрібно мати достатньо оперативної пам’яті, щоб утримувати цю таблицю.
  2. Столи втрачаються, якщо машина вимикається.

Я вважаю, що №1 не має бути проблемою, оскільки я використовую AWS EC2 і, якщо потрібно, можна перейти до типу екземпляра з більшою кількістю пам'яті. Я вважаю, що можу пом'якшити номер 2, повернувшись на диск за потребою.

Які ще проблеми є? Чи може мотор пам'яті коли-небудь давати гірші показники, ніж MyISAM чи InnoDB? Я думаю, що я прочитав щось, що показники відрізняються у цього двигуна; це щось, про що я повинен хвилюватися?

Відповіді:


27

Переглядаючи список доступних функцій на веб- сайті http://dev.mysql.com/doc/refman/5.1/uk/memory-storage-engine.html, вискакують дві можливі проблеми:

  1. Жодна транзакція чи підтримка FK, тобто вам доведеться керувати цілісністю транзакцій та референтною цілісністю у власному коді (що може виявитись набагато менш ефективним, ніж дозволяти БД робити це за вас, хоча це дуже залежить від вашої програми очікувані моделі поведінки).
  2. Блокування лише рівня таблиці: це може бути суттєвим бар'єром для масштабованості, якщо вашій програмі потрібні кілька одночасних авторів запису в одному наборі таблиць або у випадках, коли ваші операції з читання використовують блокування для забезпечення послідовного зчитування даних - у таких випадках таблиця на основі диска, яка підтримує набагато більш тонку деталізацію блокування, вона буде працювати набагато краще, якщо достатньо її вмісту буде кешовано в оперативній пам'яті.

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

Альтернативою може бути:

  1. Використовуйте на основі дискових таблиць, але переконайтеся, що у вас є більш ніж достатня оперативна пам’ять, щоб утримати їх усіх в оперативній пам’яті в будь-який момент часу (і «достатня кількість оперативної пам’яті» може бути більше, ніж ви думаєте, як вам потрібно враховувати будь-які інші процеси на машині, ОС Буфери IO / кеш тощо)
  2. Скануйте весь вміст (усі дані та сторінки покажчиків) таблиці під час кожного запуску, щоб попередньо завантажити вміст у пам'ять SELECT * FROM <table> ORDER BY <pkey fields>для кожної таблиці, а потім SELECT <indexed fields> FROM <table> ORDER BY <index fields>для кожного індексу

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


Навіщо вам потрібна цілість транзакцій для бази даних в пам'яті? Якщо живлення вимкнеться, ви все одно втрачаєте все.
оса

@osa: якщо припустити, що це дозволяє одночасний доступ, а не серіалізацію всього, ви хочете отримати для цього певну форму управління цілісністю.
Девід Спіллетт

14

Немає випадків, коли не використовувати механізм зберігання пам’яті - і коли InnoDB буде швидше. Потрібно просто думати про одночасність, а не про банальні тести з однорядними потоками.

Якщо у вас достатньо великий буферний пул, InnoDB стане повністю резидентом пам'яті і для операцій з читанням. Бази даних мають кеші . Вони зігрівають себе!

Також не варто недооцінювати значення блокування на рівні рядків та MVCC (читачі не блокують записувачів). Це може бути "повільніше", коли записи повинні зберігатися на диску. Але принаймні ви не будете блокувати під час цієї операції запису, як ви знаходитесь у таблиці пам'яті (немає MVCC; блокування рівня таблиці).


3

Для запису. Я тестував таблиці Mysql в Пам'яті для зберігання деякої інформації. І я перевірив APC (APCu) PHP для зберігання тієї самої інформації.

Для 58000 реєстрів. (varchar + integer + дата).

  1. Оригінальна інформація 24 Мб у текстовому форматі (формат csv).
  2. APC PHP використовує 44,7 Мб оперативної пам’яті.
  3. Таблиця Mysql використовує 575 Мб оперативної пам’яті.

У таблиці є лише один індекс, тому я не думаю, що це головний фактор.

Висновок:

Таблиця пам'яті не є варіантом для "великих" таблиць, оскільки вона використовує занадто багато пам'яті.


2
Це спрощена відповідь. Двигун пам'яті MEMORY може бути налаштований за допомогою менших типів даних, чітко визначаючи BTREE як тип індексу та обмежуючи кількість даних, завантажених в оперативну пам'ять. Це все ще життєздатний варіант для менших наборів. Існують також інші фактори, такі як агресивний диск вводу / виводу. Дивіться мої повідомлення dba.stackexchange.com/questions/6156/… та dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA

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

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 за допомогою двигуна ПАМ’ЯТЬ.
Матвій1471,

2

Іншим недоліком таблиць, заснованих на ПАМ’ЯТКІ, є те, що їх не можна пересилати кілька разів в одному запиті. Принаймні, така поведінка була виявлена ​​до версії 5.4. Як з CTE (починаючи з v8.x), немає необхідності використовувати проміжні таблиці на основі mem для складних процедур.


1

Згідно з посібниками MySQL та MariaDB, BLOB та CLOB (різні типи TEXT) не підтримуються пам'яттю MEMORY. Для наших власних цілей це зробило двигун пам’яті MEMORY майже марним.

http://dev.mysql.com/doc/refman/5.7/uk/memory-storage-engine.html

Таблиці MEMORY не можуть містити стовпці BLOB або TEXT.

https://mariadb.com/kb/en/mariadb/memory-storage-engine/

Типи змінної довжини, такі як VARCHAR, можна використовувати в таблицях ПАМ’ЯТЬ. Стовпчики BLOB або TEXT не підтримуються для таблиць MEMORY.

Коли я намагався перетворити лише частину бази даних у пам'ять MEMORY, я виявив, що сторонні ключі двигуна для зберігання не підтримуються. Отже, всі таблиці, на яких повинні бути посилання іноземних ключів на таблиці, що містять BLOB / CLOB, також повинні знаходитись у типах пам'яті, що не зберігається в пам'яті (принаймні, це стосується дочірніх таблиць InnoDB).


1

Таблиці MEMORY не призначені для постійного зберігання, особливо для великих наборів даних або будь-якого іншого, коли зберігання є критичним. З мого досвіду їх найкраще призначення - зберігати перехідні записи під час створення та заселення тимчасових таблиць під час складних процедур, яка виконує значно швидше, ніж для більшості інших типів таблиць для цієї мети, за умови, що ваш ключовий поріг буфера для двигуна встановлений досить високо, щоб не виникати запис на диск. Це може працювати на порядок швидше, ніж MyISAM або InnoDB для цієї мети, оскільки немає вводу / виводу диска, а у випадку таблиці, яка інкапсульована в рамках певної процедури, індексація та відносини не мають такого значущого значення, як вони там, де очікується наполегливість.


1

Окрім попередніх відповідей. прямо з керівництва MySQL 5.7:

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

... і це дуже реальне обмеження. Наприклад: коли у вас є кілька сеансів, які намагаються створити приємні швидкі темпні пам'яті MEMORY, однопотокова передача може призвести до серйозного вузького місця.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.