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

857

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

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

У кого-нибудь есть опыт работы с этим типом нагрузки (или выше)? MyISAM - это путь?

user2013
источник
13
Блог производительности MySQL является большим ресурсом для такого рода вещи.
ceejayoz
3
Это будет зависеть от того, является ли ваша система OLTP или больше ориентирована на хранилище данных (где большинство операций записи - это массовая загрузка).
Нос
35
MyISAM не поддерживает блокировку строк, транзакции, он даже не поддерживает внешние ключи ... черт, поскольку он не может предоставить ACID , его вряд ли можно считать подходящей базой данных! Вот почему InnoDB был механизмом по умолчанию с MySQL 5.5 ... но по какой-то причине MyISAM продолжает оставаться механизмом по умолчанию для таблиц, созданных в PhpMyAdmin, поэтому многие любительские базы данных с тех пор работают на MyISAM.
BlueRaja - Дэнни Пфлугхофт
Посмотрите это rackspace.com/knowledge_center/article/…
Кришна

Ответы:

523

Я кратко обсудил этот вопрос в таблице, чтобы вы могли прийти к выводу, стоит ли идти с InnoDB или MyISAM .

Вот небольшой обзор того, какой механизм хранения БД вы должны использовать в какой ситуации:

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

Резюме

  • Почти во всех случаях InnoDB - лучший путь
  • Но, частое чтение, почти не пишу, используйте MyISAM
  • Полнотекстовый поиск в MySQL <= 5.5, используйте MyISAM
developer99
источник
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.

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

rix0rrr
источник
12
Близко к 200? Если его средняя транзакция составляет 2,5 запроса, это [(2,5 * 1M) / 3600s =] ближе к 700.
Оззи
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/en/too-many-connections.html ).
Оззи
152
Когда таблица заблокирована, к ней может одновременно работать только один запрос. Неважно, поддерживает ли сервер 10000 одновременных соединений, каждое из них будет выполнять резервное копирование, пока таблица заблокирована.
Райанер
2
Также может быть полезно знать, что MyISAM поддерживает пространственный индекс, а InnoDB - нет. И MyISAM, похоже, не использует внешние ключи, хотя это не мешает их создавать.
Кривер
4
@kriver: Вы не можете иметь внешние ключи в таблицах MyISAM. Вы можете включить определения FK в операторы CREATE TABLE, но они (определения) просто игнорируются.
ypercubeᵀᴹ
191

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

Попробуй это:

  1. Введите UPDATE для своей таблицы MyISAM, что займет 5 секунд.
  2. Пока выполняется ОБНОВЛЕНИЕ, скажем, через 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 (kill -9) или какой-нибудь сбойный сигнал (или он заработает его сам по себе, когда обнаружит ошибку), или если ОС выйдет из строя / пропадет питание, то это другая история - вы можете увидеть Коррупция на уровне MyISAM.
Саша Пачев
1
InnoDB также может по-королевски портить себя, обычно более по-королевски, чем MyISAM. Ирония ACID в том, что у нас есть понятие «все или ничего». Поэтому, когда InnoDB не может дать все, он ничего не дает - внутреннее утверждение, и он вообще отказывается запускаться, потому что один байт в некоторой структуре неверен - 90% времени он мог бы быть проигнорирован, и это в лучшем случае затронуло бы только одну таблицу. Последние серверы Percona имеют возможность справиться с этим - innodb_pass_corrupt_table.
Саша Пачев
1
Я искал такую ​​информацию за последние 3 дня, теперь я получил это. InnoDB лучше. СпасибоBill Karwin
user3833682
3
@ flow2k, в наши дни почти нет. На моей последней работе мы использовали MyISAM для одной таблицы на одном сервере, и единственная причина заключалась в том, что MyISAM могла хранить эту конкретную таблицу в меньшем пространстве, чем InnoDB. Мы были ограничены дисковым пространством, поэтому нам пришлось использовать MyISAM, пока мы не смогли перенести базу данных на другой сервер. На моей новой работе уже есть политика, что каждая таблица должна быть InnoDB.
Билл Карвин
138

Я работал над системой большого объема, используя MySQL, и я пробовал и MyISAM, и InnoDB.

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

В конце концов, я решил проблему с конфликтами, разбив данные таким образом, что вставки помещались в «горячую» таблицу и выбирали никогда не запрашиваемую горячую таблицу.

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

Конечно, я понятия не имею, что представляет собой ваше приложение, но, надеюсь, это даст вам некоторое представление о некоторых проблемах с MyISAM и InnoDB.

alanc10n
источник
3
«В конце концов я решил проблему с разногласиями, разбив данные таким образом, что вставки помещались в« горячую »таблицу и выбирали никогда не запрашиваемые горячие таблицы».
Разве
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 будет автоматически восстанавливать через воспроизведение этих журналов.

ПОЛНАЯ ТЕКСТОВАЯ индексация

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

Однако это не является веской причиной для использования MyISAM. Лучше всего перейти на хостинг-провайдера, который поддерживает современные версии MySQL. Не то, чтобы таблица MyISAM, использующая индексирование FULLTEXT, не могла быть преобразована в таблицу InnoDB.

Вывод

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

d4nyll
источник
Я делал скрипт контрольной суммы сеанса 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).

Но ориентир безусловно.

staticsan
источник
4
Является ли "InnoDB commit flush", на который вы ссылаетесь 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.
тымтам
Очень информативный пост. У меня был тот же вопрос, что и у оп, и я должен сказать, что ваш пост облегчил мне решение о ядре базы данных. Спасибо! ++
Джо Маевски
Краткое примечание: задержка больше не поддерживается в 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' и 'memory' во второй и третьей таблицах.

 

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) )

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

StackG
источник
1
производительность не всегда является единственным фактором, как насчет графика стабильности? двигатель не годится ни для чего, если он выходит из строя и не поддерживает базовые функции базы данных.
Pilavdzice
1
MyISAM, вероятно, будет бить InnoDB в большинстве случаев, если my.cnfфайл не оптимизирован для InnoDB. Вы не упомянули, как my.cnfвыглядит ваш файл, что действительно является наиболее важным фактором для производительности InnoDB.
итопопус
Спасибо, itoctopus - я хотел бы услышать больше о любых оптимизациях, которые вы рекомендуете. Полный код, использованный в этих тестах, приведен выше, не стесняйтесь повторять эксперименты с различными оптимизациями и дайте нам знать, если вы обнаружите значительные изменения в результатах
StackG
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 (*) (когда 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 КБ, было немного тревожным.
Риного
См. Mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb для получения дополнительной информации.
Билл Карвин
Ответ уже не актуален, так как движок 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 и других - они могут быть интересны, если вы все еще не можете получить достаточную производительность без них.

MarkR
источник
24

Вопрос и большинство ответов устарели .

Да, это история старых жен, что MyISAM работает быстрее, чем InnoDB. обратите внимание на дату Вопроса: 2008; сейчас почти десятилетие спустя. С тех пор InnoDB добился значительных успехов.

Драматический график был для одного случая , когда MyISAM выигрывает: COUNT(*) без в WHEREп. Но разве это то, чем ты занимаешься?

Если вы запустите тест на параллелизм , InnoDB, скорее всего, победит, даже противMEMORY .

Если вы делаете какие-либо записи во время бенчмаркинга SELECTs, MyISAM и MEMORY, скорее всего, проиграют из-за блокировки на уровне таблицы.

На самом деле Oracle настолько уверен, что InnoDB лучше, чем когда-либо, но они удалили MyISAM из 8.0.

Вопрос был написан в начале дня 5.1. С тех пор эти основные версии были отмечены как «общедоступные»:

  • 2010: 5,5 (0,8 в декабре)
  • 2013: 5,6 (0,10 в феврале)
  • 2015: 5,7 (0,9 в октябре)
  • 2018: 8,0 (0,11 в апреле)

Итог: не используйте MyISAM

Рик Джеймс
источник
2
Усовершенствования технологии баз данных MySQL. А вопрос и ответы StackOverflow остаются в прошлом. В основных различиях между MyISAM и InnoDB являются менее о «нагрузке» на сервере, и более о поддержке ссылочной целостности и операциях , а также параллельности и возвратности (+10)
spencer7593
12

Также проверьте некоторые вставные замены для самого MySQL:

MariaDB

http://mariadb.org/

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

Percona Server

https://launchpad.net/percona-server

Усовершенствованная замена MySQL с возможностью быстрой замены, улучшенной производительностью, улучшенной диагностикой и дополнительными функциями.

рафинер
источник
1
Я использую их обоих (Percona на производстве, Мария на Windows-разработке). они быстрее и работают безупречно.
Моше Л
4
Это не отвечает на вопрос. MariaDB и Percona являются форками MySQL и также используют движки InnoDB и MyISAM.
dr_11.11
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 имеет больше механизмов, чтобы избежать подобных вещей ...

В любом случае, я вполне уверен, что согласен с теми, кто утверждал, что количество соединений, разрешенных за один раз , не работает за закрытым столом. Фактически, множественные соединения - это единственная цель блокировки таблицы! Так что другие процессы / пользователи / приложения не могут повредить базу данных, одновременно внося изменения.

Как два или более соединения, работающие в одном ряду, сделают ДЕЙСТВИТЕЛЬНО ПЛОХОЙ ДЕНЬ для вас ?? Предположим, что есть два процесса, которые хотят / должны обновить одно и то же значение в одной и той же строке, скажем, потому что строка является записью автобусного тура, и каждый из двух процессов одновременно хочет обновить «riders» или «available_seats» поле как «текущее значение плюс 1»

Давайте сделаем это гипотетически, шаг за шагом:

  1. Первый процесс считывает текущее значение, скажем, оно пустое, поэтому пока '0'.
  2. Второй процесс также читает текущее значение, которое по-прежнему равно 0.
  3. Процесс один пишет (текущий + 1), который равен 1.
  4. Процесс два должен записывать 2, но поскольку он читает текущее значение, а процесс 1 записывает новое значение, он также записывает 1 в таблицу.

Я не уверен, что два соединения могут так смешиваться, оба читают, прежде чем первое пишет ... Но если нет, то я все равно вижу проблему с:

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

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

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

И, увы, если вы знаете об этих проблемах параллелизма, да, вы можете играть в нее менее безопасно и просто писать свои приложения, настроить свои системы так, чтобы такие ошибки были невозможны (ваш код ответственен, а не сама база данных). Однако, по моему мнению, я бы сказал, что всегда лучше использовать как можно больше защитных мер, программируя в обороне и всегда осознавая, что человеческую ошибку невозможно полностью избежать. Это случается со всеми, и любой, кто говорит, что он неуязвим к этому, должен лгать или делать больше, чем просто написать приложение / скрипт "Hello World". ;-)

Я надеюсь, что НЕКОТОРЫЕ из этого будут полезны кому-то, и тем более, я надеюсь, что я не только сейчас был виновником предположений и ошибкой человека !! Мои извинения, если да, но примеры, о которых стоит подумать, исследовать риск и т. Д., Даже если они не являются потенциальными в этом конкретном контексте.

Не стесняйтесь поправлять меня, редактировать этот «ответ», даже голосовать за него. Просто, пожалуйста, попробуйте улучшить, а не исправлять мое неверное предположение другим. ;-)

Это мой первый ответ, поэтому, пожалуйста, извините за длину из-за всех заявлений об отказе от ответственности и т.д ... Я просто не хочу звучать высокомерно, когда я не совсем уверен!

Arembjorn
источник
5

По моему опыту, MyISAM был лучшим выбором, если вы не выполняете УДАЛЕНИЯ, ОБНОВЛЕНИЯ, множество отдельных операций ВСТАВКИ, транзакций и полнотекстовой индексации. Кстати, проверить таблицу ужасно. Поскольку таблица стареет с точки зрения количества строк, вы не знаете, когда она закончится.

yogman
источник
2
Полнотекстовая индексация возможна только с MyISAM, но не с InnoDB.
Pixel Elephant
2
@PixelElephant, это начинает меняться в MySQL 5.6. InnoDB имеет тип полнотекстового индекса, но пока он не готов к использованию.
Билл Карвин
1
«Полнотекстовая индексация возможна только с MyISAM, но не с InnoDB»: не более, так как MySQL> = 5.6. См. Dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57
5

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

Рикардо
источник
4

Каждое приложение имеет свой собственный профиль производительности для использования базы данных, и есть вероятность, что он со временем изменится.

Лучшее, что вы можете сделать, это проверить свои варианты. Переключение между MyISAM и InnoDB тривиально, поэтому загрузите некоторые тестовые данные и запустите Jmeter для своего сайта и посмотрите, что произойдет.

Гари Ричардсон
источник
4

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

user965748
источник
2
Вы получите такую ​​же производительность, если будете использовать транзакцию и отключите автокоммит для движка InnoDB.
stanleyxu2005
IDK, если та же производительность, но это то, что я делаю в более сложных приложениях, и это ускоряет его.
user965748
1
Вы не смогли предоставить точные детали вашего эксперимента - какие параметры конфигурации? Что было в таблицах раньше? Какие данные? и, возможно, самое главное - были ли вставки последовательными? Параллельно? Каково было их время? Сколько ядер процессора? Потоки? и т. д.
einpoklum
3

myisam является NOGO для такого типа рабочей нагрузки (записи с высокой степенью параллелизма), у меня нет такого большого опыта работы с innodb (тестировал его 3 раза и в каждом случае обнаруживал, что производительность отстой, но прошло некоторое время с момента последнего теста), если вы Вы не обязаны запускать MySQL, попробуйте попробовать Postgres, поскольку он обрабатывает одновременные записи намного лучше

pfote
источник
3

Короче говоря, InnoDB хорош, если вы работаете над чем-то, что требует надежной базы данных, которая может обрабатывать множество инструкций INSERT и UPDATE.

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

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

Light93
источник
2

Я знаю, что это не будет популярно, но здесь идет:

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

Не использовать ссылочную целостность или транзакции в мире баз данных все равно, что не использовать объектно-ориентированное программирование в мире программного обеспечения.

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

Нет, это не имеет значения, если вы читаете или пишете, или какие у вас соображения по поводу производительности, использование myISAM может привести к множеству проблем, таких как эта, с которой я только что столкнулся: я выполнял синхронизацию базы данных, и в то же время кто-то другой получил доступ к приложению, которое получило доступ к таблице, установленной в myISAM. Из-за отсутствия поддержки транзакций и в целом низкой надежности этого движка это привело к сбою всей базы данных, и мне пришлось вручную перезапустить mysql!

За последние 15 лет разработки я использовал много баз данных и движков. MyISAM обрушился на меня около десятка раз за этот период, другие базы данных, только один раз! И это была база данных Microsoft SQL, где какой-то разработчик написал неисправный код CLR (общеязыковая среда выполнения - в основном код C #, который выполняется внутри базы данных), кстати, это не было ошибкой ядра базы данных.

Я согласен с другими ответами, в которых говорится, что качественные высокодоступные и высокопроизводительные приложения не должны использовать myISAM, так как он не будет работать, он недостаточно надежен или стабилен, чтобы обеспечить бесперебойную работу. См. Ответ Билла Карвина для более подробной информации.

PS Должен любить, когда фанаты myISAM понижают голос, но не могут сказать, какая часть этого ответа неверна.

pilavdzice
источник
5
я не понизил голос, но если бы я сделал это, то для того, чтобы советовать никогда не использовать. слово никогда не должно быть зачеркнуто в словаре разработчика ... будьте осторожны, никогда не говори никогда.
Хабсон Бропа
1

Для такого отношения чтения / записи я бы предположил, что InnoDB будет работать лучше. Так как вы хорошо справляетесь с грязным чтением, вы можете (если вы позволите) копировать его на подчиненное устройство и позволить всем своим прочтениям перейти на подчиненное устройство. Кроме того, рассмотрите возможность вставки навалом, а не по одной записи за раз.

Neal Aise
источник
1

Почти каждый раз, когда я начинаю новый проект, я задаю один и тот же вопрос в Google, чтобы узнать, получу ли я какие-нибудь новые ответы.

Это в конечном итоге сводится к - я беру последнюю версию MySQL и запускаю тесты.

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

Таким образом, мы не говорим о сложной системе, мы говорим о простом поиске ... и о том, как (кроме создания резидентной ОЗУ таблицы) мы можем оптимизировать производительность.

Я также делаю тесты на других базах данных (например, NoSQL), чтобы узнать, есть ли где-нибудь, где я могу получить преимущество. Самое большое преимущество, которое я обнаружил, - это сопоставление клавиш, но в плане поиска MyISAM в настоящее время возглавляет их все.

Хотя я не буду выполнять финансовые транзакции с таблицами MyISAM, но для простых поисков вы должны проверить это ... обычно от 2 до 5 раз запросов / сек.

Проверьте это, я приветствую дебаты.

Cyberwip
источник
1

Если это 70% вставок и 30% читает, то это больше похоже на сторону InnoDB.

КТА
источник
0

Итог: если вы работаете в автономном режиме с выборками на больших порциях данных, MyISAM, вероятно, даст вам лучшую (намного лучшую) скорость.

Есть некоторые ситуации, когда MyISAM бесконечно более эффективен, чем InnoDB: при работе с большими дампами данных в автономном режиме (из-за блокировки таблицы).

Пример: я конвертировал CSV-файл (15M записей) из 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).

Тони Гил
источник