MyISAM проти InnoDB [закрито]


857

Я працюю над проектами, які передбачають багато записів у базу даних, я б сказав ( 70% вставок і 30% читає ). Це співвідношення також включатиме оновлення, які я вважаю одним читанням та одним записом. Читає може бути забруднений (наприклад , не потрібно 100% точної інформації під час читання).
Завдання, про яке йдеться, буде робити понад 1 мільйон транзакцій із базою даних на годину.

Я прочитав в Інтернеті купу матеріалів про відмінності між MyISAM та InnoDB, і MyISAM здається мені очевидним вибором для конкретної бази даних / таблиць, яку я буду використовувати для цього завдання. З того, що я начебто читаю, InnoDB добре, якщо потрібні транзакції, оскільки підтримується блокування рівня рядків.

Хтось має досвід із цим типом навантаження (або вище)? Чи мій шлях MyISAM?


13
Блог продуктивності MySQL є великим ресурсом для такого роду речі.
ceejayoz

3
Це дещо залежатиме від того, чи орієнтована ви на систему OLTP або більше сховищ даних (де більшість записів завантажується масово).
нос

35
MyISAM не підтримує блокування рядків, транзакції, він навіть не підтримує сторонні ключі ... пекло, оскільки він не може надати ACID , навряд чи він може вважатися належною базою даних! Ось чому InnoDB був двигуном за замовчуванням з MySQL 5.5 ..., але з будь-якої причини MyISAM продовжує залишатися двигуном за замовчуванням для таблиць, створених у PhpMyAdmin, тому багато баз даних любителів з моменту запуску на MyISAM.
BlueRaja - Danny Pflughoeft


Відповіді:


523

Я коротко обговорив це питання в таблиці, щоб ви могли зробити висновок, чи варто їхати з InnoDB чи MyISAM .

Ось невеликий огляд, який зберігання БД двигуна слід використовувати в якій ситуації:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Необхідний повнотекстовий пошук Так 5.6.4
-------------------------------------------------- --------------
Вимагати угоди Та
-------------------------------------------------- --------------
Часті запити виберіть Так      
-------------------------------------------------- --------------
Часті вставки, оновлення, видалення Так
-------------------------------------------------- --------------
Блокування рядків (багаторазова обробка на одному столі) Так
-------------------------------------------------- --------------
Реляційна базова конструкція Так

Підсумок

  • Майже в усіх обставинах InnoDB - найкращий шлях
  • Але, часте читання, майже не писати, використання MyISAM
  • Повнотекстовий пошук у MySQL <= 5.5, використовуйте MyISAM

11
InnoDB має повнотекстові індекси в MySQL 5.6, але поки що вони не дуже готові до використання у виробництві.
Білл Карвін

3
Надавати до 12,9. Повнотекстові функції пошуку : "Повнотекстові індекси можна використовувати лише в таблицях InnoDB або MyISAM". Схоже, для MySQL> = 5.6, однак на тій же самій сторінці для MySQL 5.5 все ще сказано: «Повнотекстові покажчики можна використовувати лише з таблицями MyISAM». У наведеній вище таблиці може бути оновлена каже , як вона відрізняється з версіями MySQL. На жаль, поки що, здається, MySQL 5.5 є стандартом.
Hibou57

2
Що означає: InnoDB - full-text: 5.6.4?? Це так чи ні?

2
MyISAM також зберігає кількість рядків внутрішньо. Тому функція Count () майже не вільна в MyISAM, тоді як в InnoDB вона займає помітну кількість часу.
Хедеши

3
хороша таблиця, але додаючи рядок за якістю та стабільністю, MyIsam = ні, innoDB = так, це зробить це ще краще
pilavdzice

268

Я не експерт по базі даних, і не кажу з досвіду. Однак:

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

Це говорить про те, що вам знадобиться двигун зберігання даних, який підтримує блокування на рівні рядків, тобто InnoDB.

З іншого боку, слід досить тривіально написати кілька простих сценаріїв для імітації навантаження з кожним двигуном зберігання, а потім порівняти результати.


12
Близько до 200? Якщо його середня транзакція складає 2,5 запиту, це [(2,5 * 1М) / 3600s =] ближче до 700.
Ozzy

12
Я також не згоден з a single query can take no more than 5msтим, що ви зробили 2 малоймовірних припущення; A: всі запити потрібно один і той же стіл & B: є тільки 1 з'єднання доступно! Я повинен повідомити вам, що налаштування Linux & MySQL 5.5 з високою оперативною пам’яттю може підтримувати до 10 000 одночасних підключень (Див.: Dev.mysql.com/doc/refman//5.5/uk/too-many-connections.html )
Озі

152
Коли таблиця заблокована, одночасно проти неї може працювати лише один запит. Не має значення, чи підтримує сервер 10000 одночасних з'єднань, кожен з них буде створювати резервну копію, поки таблиця заблокована.
Ryaner

2
Також може бути корисно знати, що MyISAM підтримує просторовий індекс, а InnoDB - ні. І, схоже, MyISAM не використовує сторонні ключі, навіть якщо це не заважає створити його.
kriver

4
@kriver: Ви не можете мати сторонні ключі в таблицях MyISAM. Ви можете включати визначення FK в оператори TABLE CREATE , але вони (визначення), просто ігноруються.
ypercubeᵀᴹ

191

Люди часто говорять про продуктивність, читають проти запису, зовнішні ключі тощо, але на мою думку, є ще одна необхідна функція двигуна зберігання даних: атомні оновлення.

Спробуйте це:

  1. Складати UPDATE проти вашої MyISAM таблиці, яка займає 5 секунд.
  2. Поки UPDATE триває, скажімо, через 2,5 секунди, натисніть Ctrl-C, щоб перервати його.
  3. Поспостерігайте за ефектами на столі. Скільки рядків було оновлено? Скільки не було оновлено? Чи таблиця навіть читабельна, або вона була зіпсована при натисканні на Ctrl-C?
  4. Спробуйте той же експеримент з UPDATE щодо таблиці InnoDB, перервавши запит, що виконується.
  5. Дотримуйтесь таблиці InnoDB. Нульові рядки були оновлені. InnoDB запевнив вас є атомні поновлення, і якщо повне оновлення не може бути скоєно, він відкочується все зміни. Також таблиця не зіпсована. Це працює, навіть якщо ви використовуєте killall -9 mysqldдля імітації аварії.

Ефективність бажана, звичайно, але не втрачаючи дані, це має козир.


4
Для запису, інші характеристики баз даних ACID - несуперечливість, ізоляції та довговічність - не підтримуються MyISAM небудь.
Білл Карвін

Control-C не повинен пошкоджувати таблицю - так як у CHECK TABLE повернеться успіх, і всі запити пройдуть без помилок. MyISAM перерве оновлення без оновлення всіх записів, але таблиця буде підтримувати внутрішню структурну цілісність. Вбивство mysqld за допомогою SIGTERM матиме такий же ефект. Однак якщо ви даєте йому SIGKILL (вбийте -9) або якийсь сигнал про збій (або він заробляє його самостійно, коли потрапляє на помилку), або якщо ОС падає / живлення втрачається, то це вже інша історія - ви можете побачити Корупція на рівні MyISAM.
Сашко Пачев

1
InnoDB може також пошкоджуватись і по-царському, як правило, більш царсько, ніж MyISAM, коли це відбувається. Іронія кислоти полягає в тому, що ми маємо поняття про все або нічого. Отже, коли InnoDB не може дати все, він нічого не дає - внутрішній аргумент, і він взагалі відмовляється виконувати, тому що один байт у якійсь структурі невірний - у 90% випадків його можна було проігнорувати, і це максимум вплине лише на одну таблицю. Останні сервери Percona мають можливість з цим боротися - innodb_pass_corrupt_table.
Саша Пачев

1
Я шукав подібну інформацію протягом останніх 3 днів, зараз я отримав цю інформацію. InnoDB найкраще. ДякуюBill Karwin
користувач3833682

3
@ flow2k, В даний час майже немає. На моїй останній роботі ми використовували MyISAM для однієї таблиці на одному сервері, і єдиною причиною було те, що MyISAM змогла зберігати цю конкретну таблицю менше місця, ніж у InnoDB. Нас обмежили дисковий простір, тому нам довелося використовувати MyISAM, поки ми не змогли перемістити базу даних на інший сервер. На моїй новій роботі вже є політика, згідно з якою кожна таблиця повинна бути InnoDB.
Білл Karwin

138

Я працював над системою з великим обсягом, використовуючи MySQL, і спробував і MyISAM, і InnoDB.

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

Врешті-решт я вирішив проблему суперечок, фрагментуючи дані таким чином, що вставки входили у "гарячу" таблицю і вибирали ніколи не запитували гарячу таблицю.

Це також дозволило видалити (дані були чутливими до часу, і ми зберегли лише X днів) на "несвіжих" таблицях, які знову не торкалися вибраних запитів. Здається, InnoDB має низьку ефективність для масових видалень, тому, якщо ви плануєте очищення даних, ви можете структурувати їх таким чином, щоб старі дані знаходились у застарілій таблиці, яку можна просто скинути замість запуску видалень.

Звичайно, я поняття не маю, що це за ваша заявка, але, сподіваємось, це дає вам деяке уявлення про деякі проблеми з MyISAM та InnoDB.


3
«Врешті-решт я вирішив проблему конкуруючої фрагментируя дані таким чином, що вставки пішли в" гарячу "таблицю і вибирає не опитано гарячу таблиця«. - це не те, що по суті те , що буферний пул для?
BlueRaja - Денні Pflughoeft

15
Денні - Ні, не дуже. Налаштування налаштувань сервера є важливим, але ні в якому разі не замінює продуману структурування вашої схеми. Якщо у вас БД набагато більша, ніж наявна ОЗУ та шаблони доступу, які довільно торкаються даних по всій БД, то вся настройка буферного пулу у світі не допоможе вам. Якщо ви розумієте дані та шаблони доступу, тоді ви можете пом'якшити більшу частину болю завдяки ретельному проектуванню.
alanc10n

66

Трохи пізно до гри ... але ось досить всеосяжний пост я написав кілька місяців тому , в якому детально основні відмінності між MyISAM і InnoDB. Візьміть чашку (а може і печиво), і насолоджуйтесь.


Основна відмінність MyISAM від InnoDB полягає в цілісності референції та транзакціях. Існують і інші відмінності, такі як блокування, зворотний відкат та повнотекстовий пошук.

Референтна доброчесність

Референтна цілісність забезпечує, щоб відносини між таблицями залишалися послідовними Більш конкретно, це означає, що у таблиці (наприклад, листи) є зовнішній ключ (наприклад, ідентифікатор продукту), що вказує на іншу таблицю (наприклад, товари), коли в таблиці, що вказується, відбуваються оновлення або видалення, ці зміни каскадуються до посилання стіл. У нашому прикладі, якщо продукт буде перейменований, зовнішні ключі зв’язкової таблиці також оновляться; якщо продукт видалено з таблиці "Продукти", будь-які списки, які вказують на видалений запис, також будуть видалені. Крім того, у будь-якому новому лістингу повинен бути той зовнішній ключ, який вказує на дійсну, існуючу запис.

InnoDB є реляційною СУБД (RDBMS) і, таким чином, має референтну цілісність, тоді як MyISAM ні.

Транзакції та атомність

Дані в таблиці керуються за допомогою операторів мови маніпуляції даними (DML), таких як SELECT, INSERT, UPDATE та DELETE. Група транзакцій два або більше операторів DML об'єднуються в єдину одиницю роботи, тому застосовується або весь блок, або жоден з них не є.

MyISAM не підтримують транзакції, тоді як InnoDB робить.

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

Якщо операція перервана під час використання таблиці InnoDB, оскільки вона використовує транзакції з атомарністю, будь-яка транзакція, яка не дійшла до завершення, не набере чинності, оскільки жодна комісія не робиться.

Блокування таблиці та рядок

Коли запит працює проти таблиці MyISAM, вся таблиця, в якій він запитується, буде заблокована. Це означає, що наступні запити будуть виконуватися лише після завершення поточного запиту. Якщо ви читаєте велику таблицю та / або є часті операції читання і запису, це може означати величезні відставання запитів.

Коли запит працює проти таблиці InnoDB, блокуються лише ті задіяні рядки, решта таблиці залишається доступною для операцій CRUD. Це означає, що запити можуть працювати одночасно в одній таблиці, за умови, що вони не використовують один і той же рядок.

Ця функція в InnoDB відома як паралельність. Як не паралельність, є головний недолік, який застосовується до вибору діапазону таблиць, оскільки існує накладні витрати на перемикання між потоками ядра, і ви повинні встановити обмеження для потоків ядра, щоб запобігти зупинці сервера. .

Угоди та відкати

Під час запуску операції в MyISAM зміни встановлюються; в InnoDB ці зміни можна повернути назад. Найпоширенішими командами, які використовуються для контролю транзакцій, є COMMIT, ROLLBACK та SAVEPOINT. 1. COMMIT - ви можете записати кілька DML-операцій, але зміни зберігатимуться лише тоді, коли буде зроблено COMMIT. 2. ROLLBACK - ви можете відмовитись від операцій, які ще не були здійснені. 3. SAVEPOINT - встановлює крапку у списку операції, до яких може відкататися операція ROLLBACK

Надійність

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

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

Індексація FULLTEXT

InnoDB не підтримує індексацію FULLTEXT до MySQL версії 5.6.4. На момент написання цього допису версія MySQL багатьох спільних хостинг-серверів все ще знаходиться нижче 5.6.4, що означає, що індексація FULLTEXT не підтримується для таблиць InnoDB.

Однак це не є вагомою причиною використання MyISAM. Найкраще перейти на хостинг-провайдера, який підтримує сучасні версії MySQL. Не те, що таблиця MyISAM, яка використовує індексацію FULLTEXT, не може бути перетворена в таблицю InnoDB.

Висновок

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


Я робив скрипт контрольної суми сеансу php, і більшість мого ключа - це випадкові рядки [az09] ... Innodb взяв на себе 30 мс, щоб зробити INSERT ON DUPLICATE KEY UPDATEтак, я спробував MyISAM, і тепер це до <1 мс ... Багато відповідей я бачив, що це innodb важко розібратися з унікальними клавішами "нестандартних" (випадкових рядків) ... Чи є у вас для цього вклад? Насправді мені було цікаво про вплив, який він мав би використати MyISAM, але ваша чудова відповідь дала мені зрозуміти, що це шлях для цього конкретного випадку.
Луї Лудог Троттьє

64

Для завантаження більшої кількості записів та читань ви отримаєте користь від InnoDB. Оскільки InnoDB забезпечує блокування рядків, а не блокування таблиць, ваші SELECTs можуть бути одночасно не тільки один з одним, але і з багатьма INSERTs. Однак, якщо ви не збираєтесь використовувати транзакції SQL, встановіть фліш InnoDB на 2 ( innodb_flush_log_at_trx_commit ). Це повертає вам багато необроблених показників, які ви б інакше втратили при переміщенні таблиць з MyISAM в InnoDB.

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

Нарешті, будьте в курсі різних навантажень таблиці. У всіх таблицях не буде однакове співвідношення читання / запису. Деякі менші таблиці з майже 100% прочитаними можуть дозволити собі залишитися MyISAM. Так само, якщо у вас є кілька таблиць, на яких майже 100% запису, ви можете отримати користь INSERT DELAYED, але це підтримується лише в MyISAM ( DELAYEDстаття ігнорується для таблиці InnoDB).

Але орієнтир, щоб бути впевненим.


4
Чи є "InnoDB flus fill", на який ви посилаєтесь innodb_flush_log_at_trx_commit?
ceejayoz

2
Я вважав ваш пост дуже корисним - дякую. В даний час оцінюю, коли використовувати MyISAM / InnoDB для моїх таблиць, і ваша публікація була корисною. Ура.
starmonkey

2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html повідомляє: Для таблиць MyISAM, якщо в середині файлу даних немає вільних блоків, одночасно підтримуються оператори SELECT та INSERT. За цих обставин вам дуже рідко потрібно використовувати INSERT DELAYED разом із MyISAM.
tymtam

Дуже інформативний пост. У мене виникло те саме питання, що і у операторів, і я повинен сказати, що ваша посада розслабила мене щодо рішення моєї бази даних. Дякую! ++
Джо Маєвський

Швидка примітка: затримка більше не підтримується в 5.7. Ви можете замість цього тестувати LOW_PRIORITY.
вебмат

59

Щоб доповнити широкий вибір відповідей, що охоплюють механічні відмінності між двома двигунами, я представляю емпіричне дослідження порівняння швидкості.

Що стосується чистої швидкості, то не завжди буває так, що MyISAM швидше, ніж InnoDB, але, на мій досвід, це, як правило, швидше для робочих середовищ PURE READ в 2,0-2,5 рази. Зрозуміло, що це не підходить для всіх середовищ - як писали інші, MyISAM не вистачає таких речей, як транзакції та зовнішні ключі.

Я трохи зробив тестування нижче - я використовував python для циклічного циклу та бібліотеку timeit для порівняння часу. Для інтересу я також включив двигун пам’яті, це дає найкращі показники в усьому світі, хоча він підходить лише для менших таблиць (ви постійно стикаєтесь, The table 'tbl' is fullколи перевищуєте ліміт пам’яті MySQL). Я переглядаю чотири типи вибору:

  1. ванільний ВИБІР
  2. рахує
  3. умовні ВИБІРИ
  4. індексований та неіндексований підселектори

По-перше, я створив три таблиці за допомогою наступного SQL

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

"MyISAM" замінено на "InnoDB" та "пам'ять" у другій та третій таблицях.

 

1) Вибирає ваніль

Запит: SELECT * FROM tbl WHERE index_col = xx

Результат: малювати

Порівняння ванілі вибирається різними двигунами бази даних

Швидкість їх загалом однакова, і, як очікується, лінійна кількість вибраних стовпців. InnoDB здається трохи швидшим, ніж MyISAM, але це дійсно незначно.

Код:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) Розраховує

Запит: SELECT count(*) FROM tbl

Результат: MyISAM виграє

Порівняння підрахунків за різними двигунами бази даних

Цей демонструє велику різницю між MyISAM та InnoDB - MyISAM (і пам'ять) відстежує кількість записів у таблиці, тому ця транзакція є швидкою та O (1). Кількість часу, необхідного для підрахунку InnoDB, збільшується надлінійно з розміром таблиці в діапазоні, який я досліджував. Я підозрюю, що багато прискорень із запитів MyISAM, які спостерігаються на практиці, зумовлені подібними наслідками.

Код:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) Умовно вибирає

Запит: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

Результат: MyISAM виграє

Порівняння умовного вибору за різними двигунами бази даних

Тут MyISAM і пам’ять виконують приблизно те ж саме, і збільшити InnoDB приблизно на 50% для більших таблиць. Це такий вид запиту, для якого переваги MyISAM, мабуть, максимізуються.

Код:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) Під-вибір

Результат: InnoDB виграє

Для цього запиту я створив додатковий набір таблиць для підбора. Кожен - це просто два стовпчики BIGINT, один з індексом первинного ключа та один без індексу. Через великий розмір столу я не випробовував двигун пам'яті. Команда створення таблиці SQL була

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

де знову "MyISAM" замінено на "InnoDB" у другій таблиці.

У цьому запиті я залишаю розмір таблиці вибору на рівні 1000000 і замість цього змінюю розмір стовпців, що виділяються.

Порівняння субселекцій за різними двигунами бази даних

Тут InnoDB легко перемагає. Після того, як ми потрапимо до таблиці розумних розмірів, обидва двигуни масштабуються лінійно за розміром під-вибору. Індекс прискорює команду MyISAM, але що цікаво мало впливає на швидкість InnoDB. subSelect.png

Код:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

Я думаю, що повідомлення про все це - якщо ви дійсно стурбовані швидкістю, вам потрібно порівняти запити, які ви робите, а не робити припущення щодо того, який двигун буде більш підходящим.


1
продуктивність не завжди є єдиною увагою, як щодо графіку стабільності? двигун не підходить ні для чого, якщо він виходить з ладу і не підтримує основні функції бази даних.
pilavdzice

1
MyISAM, ймовірно, бив InnoDB більшість разів, якщо my.cnfфайл не оптимізований для InnoDB. Ви не згадали, як my.cnfвиглядає ваш файл, що насправді є найважливішим фактором для роботи InnoDB.
іктоктоп

Спасибі itoctopus - я хотів би почути більше про будь-які оптимізації, які ви рекомендуєте. Повний код, використаний у цих тестах, вище,
сміливо

32

Трохи поза темою, але для цілей документації та повноти я хочу додати наступне.

Як правило, використання InnoDB призведе до набагато меншої складної програми, ймовірно, також більш без помилок. Оскільки ви можете помістити всю референтну цілісність (обмеження іноземних ключів) в модель даних, вам не потрібно десь поруч стільки коду програми, скільки вам потрібно для MyISAM.

Кожен раз, коли ви вставляєте, видаляєте або замінюєте запис, ви повинні перевірити та підтримувати зв’язки. Наприклад, якщо ви видалите батьків, всі діти також повинні бути видалені. Наприклад, навіть у простій системі блогів, якщо ви видалите запис блогового повідомлення, вам доведеться видалити записи коментарів, лайки тощо. У InnoDB це робиться автоматично механізмом бази даних (якщо ви вказали протипоказання в моделі ) і не потребує коду програми. У MyISAM це доведеться закодувати у програму, що дуже складно на веб-серверах. Веб-сервери за своєю природою дуже одночасні / паралельні, і тому, що ці дії повинні бути атомними, а MyISAM не підтримує реальних транзакцій, використання MyISAM для веб-серверів ризиковано / схильне до помилок.

Також у більшості загальних випадків InnoDB буде працювати набагато краще з кількох причин, одна з них зможе використовувати блокування запису рівня на відміну від блокування на рівні таблиці. Не тільки в ситуації, коли записи частіші, ніж читання, також у ситуаціях зі складними з'єднаннями на великих наборах даних. Ми помітили 3-кратне підвищення продуктивності лише за допомогою таблиць InnoDB над таблицями MyISAM для дуже великих приєднань (займає кілька хвилин).

Я б сказав, що загалом InnoDB (використовуючи 3NF-модуль даних з референтною цілісністю) повинен бути вибором за замовчуванням при використанні MySQL. MyISAM слід застосовувати лише у дуже конкретних випадках. Це, швидше за все, буде працювати менше, і призведе до більшого і більш глючного застосування.

Сказавши це. Datamodelling - це мистецтво, яке рідко зустрічається серед веб-дизайнерів / програмістів. Без образи, але це пояснює, що MyISAM використовується так сильно.


31

InnoDB пропонує:

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

У InnoDB всі дані підряд, крім TEXT та BLOB, можуть займати не більше 8000 байт. Не існує повноцінного індексування тексту для InnoDB. У InnoDB COUNT (*) s (коли WHERE, GROUP BY або JOIN не використовується) виконується повільніше, ніж у MyISAM, оскільки кількість рядків не зберігається внутрішньо. InnoDB зберігає дані та індекси в одному файлі. InnoDB використовує буферний пул для кешування даних і індексів.

MyISAM пропонує:

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

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

Загалом, я б рекомендував InnoDB для більшості цілей, а MyISAM лише для спеціалізованих цілей. Зараз InnoDB є двигуном за замовчуванням у нових версіях MySQL.


2
fwiw, VARCHAR в InnoDB також може переходити на сторінки, що переповнюються, як BLOB і TEXT. Усі ці типи даних зберігаються аналогічно всередині.
Білл Карвін

Приємно знати, @BillKarwin! Ми широко використовуємо VARCHAR у нашому додатку, і те, що VARCHAR сприяє цьому ~ 8 кБ, було дещо важливим.
rinogo


відповідь не оновлюється більше, оскільки двигун innodb у MySQL версії 5.6+ і сьогодні також підтримує повну індексацію тексту, а також MySQL 5.5 + / 5.7 + підтримує типи просторових даних (5.5+) та просторові індекси (r-tee) (5.7+) .. Для найкращої підтримки вам, як мінімум, потрібна версія MySQL 5.7+
Raymond Nijland

25

Якщо ви використовуєте MyISAM, ви не будете робити жодних транзакцій за годину, якщо ви не вважатимете кожен DML-заявою транзакцією (яка, в будь-якому випадку, не буде довговічною або атомною у випадку аварії).

Тому я думаю, що вам доведеться використовувати InnoDB.

300 транзакцій в секунду звучить як дуже багато. Якщо вам абсолютно потрібні ці транзакції, щоб вони були тривалими через відключення електроенергії, переконайтеся, що ваша підсистема вводу-виводу може легко справлятися з цим багатьма записами в секунду. Вам знадобиться хоча б RAID-контролер з кешем, підтримуваним акумулятором.

Якщо ви можете скористатися невеликим ударом про довговічність, ви можете використовувати InnoDB з innodb_flush_log_at_trx_commit, встановленим на 0 або 2 (докладні відомості див. У документах), ви можете покращити продуктивність.

Існує ряд виправлень, які можуть збільшити одночасність з боку Google та інших - вони можуть зацікавити, якщо ви все ще не можете отримати достатню продуктивність без них.


24

Питання та більшість відповідей застаріли .

Так, це казка старих дружин, що MyISAM швидше, ніж InnoDB. зауважте дату питання: 2008; зараз це майже через десятиліття. З того часу InnoDB досягла значних успіхів.

Драматичний графік був для одного випадку , коли MyISAM виграє: COUNT(*) без в WHEREп. Але це дійсно те, на що ви проводите свій час?

Якщо запустити паралелізм тест, InnoDB, досить імовірно , щоб виграти, навіть протиMEMORY .

Якщо ви робите якісь записи під час тестування SELECTs, MyISAM і MEMORY, швидше за все, втратять через блокування рівня таблиці.

Насправді Oracle настільки впевнений, що InnoDB краще, ніж у них є все, крім видаленого MyISAM з 8.0.

Питання був написаний на початку дня 5.1. Відтоді ці основні версії були позначені "Загальна доступність":

  • 2010: 5,5 (.8 у грудні)
  • 2013: 5,6 (.10 лютого)
  • 2015: 5,7 (.9 у жовтні)
  • 2018: 8,0 (.11 квітня)

Підсумок: Не використовуйте MyISAM


2
Удосконалення технології баз даних MySQL. І питання та відповіді StackOverflow залишаються занедбаними в минулому. В основних відмінностях між MyISAM і InnoDB є менш про «навантаженні» на сервері, і більш про підтримку посилальної цілісності і операціях , а також паралельності і зворотності (+10)
spencer7593

12

Ознайомтесь також із деякими замінами, що випадають для самого MySQL:

MariaDB

http://mariadb.org/

MariaDB - сервер баз даних, який пропонує функцію заміни, що випадає для MySQL. MariaDB створений деякими оригінальними авторами MySQL за допомогою широкої спільноти розробників вільних та відкритих програм. На додаток до основної функціональності MySQL, MariaDB пропонує багатий набір покращених функцій, включаючи альтернативні системи зберігання даних, оптимізацію сервера та виправлення.

Сервер Percona

https://launchpad.net/percona-server

Покращена заміна спаду для MySQL з кращою продуктивністю, покращеною діагностикою та додатковими функціями.


1
Я використовую обидва (Percona у виробництві, Марія на розробці windows). вони швидше і працюють бездоганно.
Моше Л

4
Це не відповідає на запитання. MariaDB та Percona - це вилки MySQL, а також використовують двигуни InnoDB та MyISAM.
dr_

12

Зауважте, що моя формальна освіта та досвід роботи з Oracle, в той час як моя робота з MySQL була повністю особистим і власним часом, тому, якщо я скажу речі, які справжні для Oracle, але не відповідають дійсності для MySQL, я вибачаюся. У той час як обидві системи багато діляться, теорія реляції / алгебра однакова, а реляційні бази даних все ще є реляційними базами даних, все ще існує велика кількість відмінностей !!

Мені особливо подобається (як і блокування на рівні рядків), що InnoDB заснований на транзакціях, це означає, що ви можете кілька разів оновлювати / вставляти / створювати / змінювати / відміняти / тощо для однієї "операції" веб-програми. Проблема, яка виникає, полягає в тому, що якщо лише деякі з цих змін / операцій закінчуються, а інші - не, ви в більшості разів (залежно від конкретного дизайну бази даних) опиняєтесь із базою даних із суперечливими даними / структурою.

Примітка. За допомогою Oracle оператори create / alter / drop називаються операторами "DDL" (визначення даних) і неявно викликають компіляцію. Встановлення / оновлення / видалення висловлювань під назвою "DML" (маніпуляція даними) не здійснюються автоматично, а лише тоді, коли виконується DDL, фіксація або вихід / вихід (або якщо ви встановили сеанс на "автоматичне фіксація", або якщо ваш клієнт автоматично погоджується). Це обов'язково слід пам’ятати про це, працюючи з Oracle, але я не впевнений, як MySQL обробляє два типи операторів. Через це я хочу дати зрозуміти, що я не впевнений у цьому, коли мова йде про MySQL; тільки з Oracle.

Приклад, коли двигуни, засновані на транзакціях, переважають:

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

У цьому випадку може бути таблиця для гостей (ім’я, телефон, електронна адреса тощо) та друга таблиця, яка відстежує кількість гостей, які підписалися. Таким чином, у нас є дві операції за одну "транзакцію". Тепер припустимо, що після того, як інформація про гостей буде додана до таблиці GUESTS, виникла втрата зв’язку або помилка з тим же впливом. Таблиця GUESTS була оновлена ​​(вставлена ​​в), але з'єднання було втрачено до того, як "доступні місця" могли бути оновлені.

Зараз до гостьового столу додається гість, але кількість доступних місць зараз неправильна (наприклад, значення становить 85, коли насправді це 84).

Звичайно, існує багато способів вирішити це, наприклад, відстеження наявних місць із "100 мінус числом рядків у таблиці гостей" або якийсь код, який перевіряє відповідність інформації тощо. Але з базою даних на основі транзакцій двигуна, такого як InnoDB, виконуються або ВСІ операції, або НІКОЛІ з них. Це може бути корисним у багатьох випадках, але, як я вже сказав, це не єдиний спосіб бути безпечним, ні (приємний спосіб, однак, керується базою даних, а не програмістом / сценаристом).

Це все "засноване на транзакціях" по суті означає в цьому контексті, якщо я чогось не пропускаю - що або вся транзакція вдається, як слід, або нічого не змінюється, оскільки внесення лише часткових змін може внести незначні зміни в СЕВЕРУ базу даних, можливо, навіть пошкоджує її ...

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

Нарешті, примітка про блокування таблиці та блокування рядків:

ВІДХОДЖЕННЯ: Можливо, я помиляюся у всьому, що випливає з MySQL, і гіпотетичні / прикладні ситуації - це питання, але я можу помилятися в тому , що саме можливо спричинити корупцію з MySQL. Приклади, однак, дуже реальні в загальному програмуванні, навіть якщо MySQL має більше механізмів, щоб уникнути подібних речей ...

У всякому разі, я досить впевнений у відповідності з тими , хто стверджував , що скільки з'єднань допускаються в той час нічого НЕ працює навколо заблоковану таблиці. Насправді кілька підключень - це вся суть блокування таблиці !! Так що інші процеси / користувачі / програми не можуть пошкодити базу даних, одночасно вносячи зміни.

Як би два чи більше з’єднань, що працюють в одному рядку, зробили ДІЙСЬКИЙ ДЕНЬ ДЛЯ ДЛЯ ВАС ?? Припустимо, є два процеси, які обидві хочуть / потребують оновлення одного і того ж значення в одному рядку, скажімо, тому, що рядок є записом автобусного туру, і кожен з двох процесів одночасно хоче оновити "вершників" або "наявних_сеансів" поле як "поточне значення плюс 1."

Зробимо це гіпотетично, крок за кроком:

  1. Один процес зчитує поточне значення, скажімо, воно порожнє, таким чином, "0" поки що.
  2. Процес два також зчитує поточне значення, яке все ще дорівнює 0.
  3. Один процес запису (поточний + 1), який дорівнює 1.
  4. Процес два повинен писати 2, але оскільки він читає поточне значення перед тим, як один процес записує нове значення, він також записує 1 у таблицю.

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

  1. Один процес зчитує поточне значення, яке дорівнює 0.
  2. Один процес запису (поточний + 1), який дорівнює 1.
  3. Процес два зчитує поточне значення зараз. Але, обробляючи одне записування (оновлення) DID, він не ввів дані, таким чином, лише той самий процес може прочитати нове значення, оновлене ним, тоді як усі інші бачать старіші значення, поки не відбудеться фіксація.

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

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

На жаль, якщо ви знаєте про ці проблеми з одночасністю, так, ви можете грати в нього менш безпечно і просто писати свої програми, налаштовувати свої системи так, щоб такі помилки були неможливі (ваш код тоді несе відповідальність, а не сама база даних). Однак, на мою думку, я б сказав, що завжди краще використовувати якомога більше гарантій, програмуючи оборонно і завжди усвідомлюючи, що людських помилок неможливо повністю уникнути. Це трапляється з усіма, і кожен, хто каже, що не застрахований від цього, повинен брехати, або не зробив більше, ніж написати заяву / сценарій "Hello World". ;-)

Я сподіваюся, що ДЕЯКІ з них є корисними для когось, і навіть більше того, я сподіваюся, що я не просто зараз був винуватцем припущень і будучи людиною в помилці !! Мої вибачення, якщо так, але на прикладах добре подумати, дослідити ризик тощо, навіть якщо вони не є потенційними в даному конкретному контексті.

Не соромтеся мене виправити, відредагуйте цю "відповідь", навіть проголосуйте за неї. Просто спробуйте вдосконалити, а не виправляти моє неправильне припущення з іншим. ;-)

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



5

На мій досвід, MyISAM був кращим вибором до тих пір, поки ви не зробите DELETEs, UPDATE, цілу партію єдиних INSERT, транзакцій та повнотекстової індексації. BTW, CHECK TABLE - жахливо. Коли таблиця старіє за кількістю рядків, ви не знаєте, коли вона закінчиться.


2
Повнотекстова індексація можлива лише з MyISAM, а не з InnoDB.
Піксельний слон

2
@PixelElephant, це починає змінюватися в MySQL 5.6. InnoDB має тип індексу повного тексту, але поки що він не готовий до виробництва IMHO.
Білл Карвін

1
"Повнотекстова індексація можлива лише з MyISAM, а не з InnoDB": не більше правдивості, оскільки MySQL> = 5.6. Див. Dev.mysql.com/doc/refman/5.6/uk/fulltext-search.html .
Hibou57

5

Я зрозумів, що незважаючи на те, що Myisam має блокуючу суперечку, він все-таки швидший, ніж InnoDb у більшості сценаріїв через швидку схему придбання блокування, яку він використовує. Я кілька разів пробував Innodb і завжди повертаюся до MyIsam з тієї чи іншої причини. Також InnoDB може бути дуже інтенсивним процесором при величезних навантаженнях на запис.


4

Кожна програма має власний профіль продуктивності використання бази даних, і швидше за все, вона зміниться з часом.

Найкраще, що ви можете зробити, це перевірити свої варіанти. Перемикання між MyISAM та InnoDB є тривіальним, тому завантажте деякі дані тесту та запустити jmeter проти свого сайту та подивіться, що відбувається.


4

Я намагався запустити вставлення випадкових даних у таблиці MyISAM та InnoDB. Результат був досить шокуючим. MyISAM знадобилося на кілька секунд менше, щоб вставити 1 мільйон рядків, ніж InnoDB лише на 10 тисяч!


2
Ви отримаєте таку ж ефективність, якщо будете використовувати транзакції та вимикати автокомісію для двигуна InnoDB.
stanleyxu2005

IDK, якщо однакова продуктивність, але це те, що я роблю в більш складних аплікатіно, і це прискорює його.
user965748

1
Вам не вдалося вказати точні дані експерименту - які налаштування конфігурації? Що було в таблиці (их) раніше? Які дані? і, можливо, найголовніше - чи були вставки послідовними? Паралельний? Який був їх термін? Скільки процесорних ядер? Нитки? пр.
einpoklum

3

myisam - це НОГО для такого типу завантаженості (пише велика сумісність), я не маю такого досвіду роботи з innodb (тестував його 3 рази і виявив у кожному випадку, що продуктивність висмоктувалась, але минулого часу минуло з останнього тесту), якщо ви Ви не змушені запускати mysql, подумайте про те, як спробувати postgres, оскільки він обробляє одночасне записування МНОГО краще


3

Коротше кажучи, InnoDB добре, якщо ви працюєте над тим, що потребує надійної бази даних, яка може обробляти безліч інструкцій INSERT та UPDATE.

і, MyISAM добре, якщо вам потрібна база даних, яка здебільшого сприймає чимало інструкцій для читання (SELECT), а не запису (INSERT та UPDATES), враховуючи її недолік у справі блокування таблиці.

ви можете перевірити;
Плюси і мінуси InnoDB
Плюси і мінуси MyISAM


2

Я знаю, що це не буде популярним, але ось що:

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

Не використовувати референтну цілісність або транзакції у світі баз даних - це не використовувати об'єктно-орієнтоване програмування у світі програмного забезпечення.

InnoDB існує зараз, використовуйте це замість цього! Навіть розробники MySQL нарешті погодилися змінити це на двигун за замовчуванням у нових версіях, незважаючи на те, що myISAM був оригінальним двигуном, який був типовим у всіх застарілих системах.

Ні, це не має значення, чи читаєте ви чи пишете, чи які у вас є міркування щодо продуктивності, використання myISAM може спричинити різні проблеми, такі як ця, в яку я щойно зіткнувся: я виконував синхронізацію бази даних і одночасно хтось інший звернувся до програми, яка отримала доступ до таблиці, встановленої в myISAM. Через відсутність підтримки транзакцій і загалом погану надійність цього двигуна, це розбило всю базу даних, і мені довелося вручну перезапустити mysql!

За останні 15 років розвитку я використав безліч баз даних та двигунів. myISAM зазнав аварії на мене близько десятка разів за цей період, інші бази даних, лише один раз! І це була база даних Microsoft SQL, де якийсь розробник написав несправний код CLR (загальна мова виконання - в основному C # код, який виконується всередині бази даних), до речі, це не була помилка двигуна бази даних саме.

Я погоджуюся з іншими відповідями тут, які говорять про те, що якісні програми з високою доступністю, високопродуктивні програми не повинні використовувати myISAM, оскільки він не працюватиме, він не є надійним або стабільним, щоб призвести до безвихідності. Дивіться відповідь Білла Карвіна для отримання більш детальної інформації.

PS Мені подобається, коли шанувальники myISAM скачують, але не можуть сказати, яка частина цієї відповіді невірна.


5
Я не заявив, але якщо я це зробив би, радимо ніколи не користуватися. Слово ніколи не повинно бути закреслено у словнику розробника ... застереження "ніколи не кажи ніколи".
губсон бропа

1

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


1

Майже щоразу, коли я запускаю новий проект, я переживаю це те саме питання, щоб дізнатися, чи придумати якісь нові відповіді.

Врешті-решт це зводиться до - я беру останню версію MySQL і запускаю тести.

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

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

Я також роблю тести на інших базах даних (тобто NoSQL), щоб побачити, чи є де-небудь я можу отримати перевагу. Найбільша перевага, яку я знайшов, полягає в картографуванні ключових даних, але, що стосується пошуку, MyISAM в даний час очолює їх усі.

Хоча я б не здійснював фінансових операцій з таблицями MyISAM, але для простих пошукових запитів ви повинні перевірити це. Зазвичай це 2 - 5 разів запити / сек.

Перевірте це, я вітаю дискусію.


1

Якщо це 70% вставок і 30% читання, то це більше схоже на сторону InnoDB.


0

нижня лінія: якщо ви працюєте в автономному режимі з вибором великих фрагментів даних, MyISAM, ймовірно, дасть вам кращі (набагато кращі) швидкості.

Є деякі ситуації, коли MyISAM нескінченно ефективніший, ніж InnoDB: при маніпулюванні великими скидами даних в режимі офлайн (через блокування таблиці).

Приклад: Я перетворював файл CSV (записи 15 М) з NOAA, який використовує поля VARCHAR як ключі. InnoDB приймав назавжди, навіть при наявності великих фрагментів пам'яті.

це приклад csv (перше і третє поля - це ключі).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

оскільки мені потрібно зробити пакетне оновлення в режимі офлайн спостережуваних погодних явищ, я використовую таблицю MyISAM для отримання даних і запускаю JOINS на клавішах, щоб я міг очистити вхідний файл і замінити поля VARCHAR клавішами INT (які пов'язані з зовнішні таблиці, де зберігаються вихідні значення VARCHAR).

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