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

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

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

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

21.08.2008 14:50:52
Блог производительности MySQL является большим ресурсом для такого рода вещи.
ceejayoz 21.08.2008 14:56:26
Это будет зависеть от того, является ли ваша система OLTP или больше ориентирована на хранилище данных (где большинство операций записи - это массовая загрузка).
nos 20.08.2010 22:18:09
MyISAM не поддерживает блокировку строк, транзакции, он даже не поддерживает внешние ключи ... черт, поскольку он не может предоставить ACID , его вряд ли можно считать подходящей базой данных! Вот почему InnoDB был механизмом по умолчанию с MySQL 5.5 ... но по какой-то причине MyISAM продолжает оставаться механизмом по умолчанию для таблиц, созданных в PhpMyAdmin, поэтому многие любительские базы данных с тех пор работают на MyISAM.
BlueRaja - Danny Pflughoeft 15.01.2013 22:43:06
Посмотрите это rackspace.com/knowledge_center/article/…
krishna 4.09.2013 11:14:38
Somnath Muluk 2.03.2016 10:38:21
25 ОТВЕТОВ

Я не эксперт по базам данных, и я не говорю из опыта. Однако:

Таблицы MyISAM используют блокировку на уровне таблиц . Исходя из ваших оценок трафика, у вас есть около 200 записей в секунду. С MyISAM только один из них может быть запущен в любое время . Вы должны убедиться, что ваше оборудование может справиться с этими транзакциями, чтобы избежать перегрузки, т. Е. Один запрос может занять не более 5 мс.

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

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

268
13.02.2011 19:18:09
Близко к 200? Если его средняя транзакция составляет 2,5 запроса, это [(2,5 * 1M) / 3600s =] ближе к 700.
Ozzy 17.04.2012 13:40:35
Я также не согласен с этим, 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 ).
Ozzy 17.04.2012 13:53:04
Когда таблица заблокирована, к ней может одновременно работать только один запрос. Неважно, поддерживает ли сервер 10000 одновременных подключений, каждое из них будет выполнять резервное копирование, пока таблица заблокирована.
Ryaner 5.09.2012 10:15:16
Также может быть полезно знать, что MyISAM поддерживает пространственный индекс, а InnoDB - нет. И MyISAM, похоже, не использует внешние ключи, хотя это не мешает их создавать.
kriver 12.09.2012 14:59:27
@kriver: Вы не можете иметь внешние ключи в таблицах MyISAM. Вы можете включить определения FK в операторы CREATE TABLE, но они (определения) просто игнорируются.
ypercubeᵀᴹ 18.09.2012 18:31:37

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

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

4
22.08.2008 17:07:16

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

Поэтому я думаю, что вы должны использовать InnoDB.

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

Если вы можете получить небольшой удар по долговечности, вы можете использовать InnoDB с innodb_flush_log_at_trx_commit, установленным в 0 или 2 (см. Документацию), вы можете улучшить производительность.

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

25
16.09.2008 21:34:54

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

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

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

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

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

138
24.11.2011 00:50:57
«В конце концов я решил проблему с разногласиями, разбив данные таким образом, что вставки помещались в« горячую »таблицу и выбирали никогда не запрашиваемые горячие таблицы».
BlueRaja - Danny Pflughoeft 15.01.2013 22:36:53
Дэнни - Нет, не совсем. Настройка параметров сервера важна, но никоим образом не заменяет вдумчивого структурирования вашей схемы. Если у вас есть БД, намного больше, чем доступная ОЗУ, и шаблоны доступа, которые случайным образом затрагивают данные по всей БД, тогда все настройки пула буферов в мире вам не помогут. Если вы понимаете данные и схемы доступа, то вы можете смягчить большую часть боли с помощью тщательного проектирования.
alanc10n 24.01.2013 05:26:45

Для загрузки с большим количеством операций записи и чтения вы получите выгоду от InnoDB. Поскольку InnoDB обеспечивает блокировку строк, а не блокировку таблиц, ваши SELECTs могут быть параллельными, не только друг с другом, но и со многими INSERTs. Однако, если вы не собираетесь использовать транзакции SQL, задайте для параметра InnoDB commit flush значение 2 ( innodb_flush_log_at_trx_commit ). Это возвращает вам большую необработанную производительность, которую вы иначе потеряли бы при перемещении таблиц из MyISAM в InnoDB.

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

Наконец, следует помнить о различных нагрузках на таблицы. Вы не будете иметь одинаковое соотношение чтения / записи во всех таблицах. Некоторые таблицы меньшего размера с почти 100% чтением могут позволить себе остаться MyISAM. Аналогично, если у вас есть несколько таблиц с почти 100% записью, вы можете извлечь из этого выгоду INSERT DELAYED, но это поддерживается только в MyISAM (это DELAYEDпредложение игнорируется для таблицы InnoDB).

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

64
28.05.2012 17:36:10
Является ли "InnoDB commit flush", на который вы ссылаетесь innodb_flush_log_at_trx_commit?
ceejayoz 5.07.2010 15:55:26
Я нашел ваш пост очень полезным - спасибо. В настоящее время оценивается, когда использовать MyISAM / InnoDB для моих таблиц и ваш пост был полезен. Приветствия.
starmonkey 25.11.2010 23:23:14
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html утверждает: для таблиц MyISAM, если в середине файла данных нет свободных блоков, поддерживаются параллельные операторы SELECT и INSERT. При таких обстоятельствах вам очень редко нужно использовать INSERT DELAYED с MyISAM.
tymtam 16.09.2011 06:20:09
Очень информативный пост. У меня был тот же вопрос, что и у оп, и я должен сказать, что ваш пост облегчил мне решение о ядре базы данных. Спасибо! ++
Joe Majewski 9.09.2012 06:06:39
Краткое примечание: задержка больше не поддерживается в 5.7. Вы можете вместо этого протестировать с LOW_PRIORITY.
webmat 5.02.2014 04:28:43

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

5
6.01.2009 00:14:42
Полнотекстовая индексация возможна только с MyISAM, но не с InnoDB.
Pixel Elephant 19.11.2012 15:10:19
@PixelElephant, это начинает меняться в MySQL 5.6. InnoDB имеет тип полнотекстового индекса, но пока он не готов к использованию.
Bill Karwin 17.07.2013 17:42:32
«Полнотекстовая индексация возможна только с MyISAM, но не с InnoDB»: не более, так как MySQL> = 5.6. См. Dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57 18.08.2013 15:57:11

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

3
31.10.2009 10:21:32

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

1
5.07.2010 15:51:58

Я думаю, что это отличная статья для объяснения различий и того, когда вы должны использовать одно над другим: http://tag1consulting.com/MySQL_Engines_MyISAM_vs_InnoDB

11
20.08.2010 22:15:32

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

5
14.09.2010 09:27:00

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

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

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

Резюме

  • Почти во всех случаях InnoDB - лучший путь
  • Но, частое чтение, почти не пишу, используйте MyISAM
  • Полнотекстовый поиск в MySQL <= 5.5, используйте MyISAM
523
7.02.2020 10:14:28
InnoDB имеет полнотекстовые индексы в MySQL 5.6, но пока они на самом деле не готовы к производственному использованию.
Bill Karwin 17.07.2013 17:39:33
Согласие с 12.9. Функции полнотекстового поиска : «Полнотекстовые индексы могут использоваться только с таблицами InnoDB или MyISAM». Кажется, нормально для MySQL> = 5.6, однако на той же странице для MySQL 5.5 все еще говорится «Полнотекстовые индексы могут использоваться только с таблицами MyISAM». Таблица выше может быть обновлена, чтобы сказать, как она отличается с версиями MySQL. К сожалению, до сих пор MySQL 5.5 кажется стандартом.
Hibou57 18.08.2013 15:50:17
Что такое среднее: InnoDB - full-text: 5.6.4?? Это да или нет?
user4795756 15.05.2015 16:19:27
MyISAM также хранит количество строк внутри. Следовательно, функция Count () в MyISAM практически бесплатна, а в InnoDB она занимает заметное количество времени.
Hedeshy 9.12.2015 10:46:16
хорошая таблица, но добавление строки для качества и стабильности, MyIsam = нет, innoDB = yes сделало бы это еще лучше
pilavdzice 2.05.2016 21:31:40

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

4
24.11.2011 00:34:25
Вы получите такую ​​же производительность, если будете использовать транзакцию и отключите автокоммит для движка InnoDB.
stanleyxu2005 26.09.2012 04:19:33
IDK, если та же производительность, но это то, что я делаю в более сложных приложениях, и это ускоряет его.
user965748 27.09.2012 07:19:39
Вы не смогли предоставить точные детали вашего эксперимента - какие параметры конфигурации? Что было в таблицах раньше? Какие данные? и, возможно, самое главное - были ли вставки последовательными? Параллельно? Каково было их время? Сколько ядер процессора? Потоки? и т. д.
einpoklum 22.10.2014 12:29:53

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

MariaDB

http://mariadb.org/

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

Percona Server

https://launchpad.net/percona-server

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

12
3.04.2012 15:49:40
Я использую их обоих (Percona на производстве, Мария на Windows-разработке). они быстрее и работают безупречно.
Moshe L 4.05.2012 09:30:52
Это не отвечает на вопрос. MariaDB и Percona являются форками MySQL и также используют движки InnoDB и MyISAM.
dr_ 11.11.2016 15:51:05

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

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

Каждый раз, когда вы вставляете, удаляете или заменяете запись, вы ДОЛЖНЫ проверять и поддерживать отношения. Например, если вы удалите родителя, все дети должны быть удалены тоже. Например, даже в простой системе ведения блогов, если вы удаляете запись публикации блога, вам придется удалять записи комментариев, лайки и т. Д. В InnoDB это выполняется автоматически механизмом базы данных (если вы указали ограничения в модели ) и не требует кода приложения. В MyISAM это должно быть закодировано в приложении, что очень сложно для веб-серверов. Веб-серверы по своей природе очень параллельны / параллельны, и поскольку эти действия должны быть атомарными, а MyISAM не поддерживает реальных транзакций, использование MyISAM для веб-серверов сопряжено с риском / подвержено ошибкам.

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

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

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

32
26.08.2012 12:18:07

Обратите внимание, что мое официальное образование и опыт работы с 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». ;-)

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

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

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

12
21.04.2013 01:54:14

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.

31
28.05.2013 07:03:17
fwiw, VARCHAR в InnoDB также может переходить на переполненные страницы, как это делают BLOB и TEXT. Все эти типы данных хранятся аналогично внутри.
Bill Karwin 17.07.2013 17:41:52
Полезно знать, @BillKarwin! Мы интенсивно используем VARCHAR в нашем приложении, и наличие VARCHAR, способствующее этому ограничению в ~ 8 КБ, было немного тревожным.
rinogo 4.11.2013 16:54:53
См. Mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb для получения дополнительной информации.
Bill Karwin 4.11.2013 16:59:45
Ответ уже не актуален, так как движок innodb в MySQL версии 5.6+ в настоящее время также поддерживает полнотекстовое индексирование, а также MySQL 5.5 + / 5.7 + поддерживает пространственные типы данных (5.5+) и пространственные индексы (r-tee) (5.7+) .. Для лучшей поддержки вам нужно было бы иметь MySQL версии 5.7+
Raymond Nijland 5.05.2019 17:15:54

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

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

  1. Введите UPDATE для своей таблицы MyISAM, что займет 5 секунд.
  2. Пока выполняется ОБНОВЛЕНИЕ, скажем, 2,5 секунды, нажмите Ctrl-C, чтобы прервать его.
  3. Обратите внимание на эффекты на столе. Сколько строк было обновлено? Сколько не было обновлено? Является ли таблица читабельной или поврежденной при нажатии Ctrl-C?
  4. Попробуйте тот же эксперимент с UPDATE для таблицы InnoDB, прервав выполняемый запрос.
  5. Соблюдайте таблицу InnoDB. Нулевые строки были обновлены. InnoDB заверил, что у вас есть атомарные обновления, и если полное обновление не может быть зафиксировано, оно откатывает все изменения. Также таблица не повреждена. Это работает, даже если вы используете killall -9 mysqldдля имитации аварии.

Производительность желательна, конечно, но не потеря данных должна превзойти это.

191
17.07.2013 17:47:27
Для записи, другие характеристики базы данных ACID - согласованность, изоляция и долговечность - также не поддерживаются MyISAM.
Bill Karwin 6.03.2014 16:12:49
Control-C не должен повреждать таблицу - так как CHECK TABLE вернет успех, и все запросы будут выполнены без ошибок. MyISAM прервет обновление, не обновляя все записи, но таблица сохранит внутреннюю структурную целостность. Уничтожение mysqld с помощью SIGTERM будет иметь тот же эффект. Однако, если вы дадите ему сигнал SIGKILL (kill -9) или какой-нибудь сбойный сигнал (или он заработает его сам по себе, когда обнаружит ошибку), или если ОС выйдет из строя / пропадет питание, то это другая история - вы можете увидеть Коррупция на уровне MyISAM.
Sasha Pachev 9.10.2015 19:13:26
InnoDB также может по-королевски портить себя, обычно более по-королевски, чем MyISAM. Ирония ACID в том, что у нас есть понятие «все или ничего». Поэтому, когда InnoDB не может дать все, он ничего не дает - внутреннее утверждение, и он вообще отказывается работать, потому что один байт в какой-то структуре неправильный - 90% времени он мог бы быть проигнорирован, и это в лучшем случае затронуло бы только одну таблицу. Последние серверы Percona имеют возможность справиться с этим - innodb_pass_corrupt_table.
Sasha Pachev 9.10.2015 19:18:46
Я искал такую ​​информацию за последние 3 дня, теперь я получил это. InnoDB лучше. СпасибоBill Karwin
user3833682 18.11.2016 12:05:03
@ flow2k, в наши дни почти нет. На моей последней работе мы использовали MyISAM для одной таблицы на одном сервере, и единственная причина заключалась в том, что MyISAM могла хранить эту конкретную таблицу в меньшем пространстве, чем InnoDB. Мы были ограничены дисковым пространством, поэтому нам пришлось использовать MyISAM, пока мы не смогли перенести базу данных на другой сервер. На моей новой работе уже есть политика, что каждая таблица должна быть InnoDB.
Bill Karwin 26.09.2017 15:18:28

Итог: если вы работаете в автономном режиме с выборками на больших порциях данных, 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).

0
6.08.2013 19:02:18

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

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

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

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

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

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

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

1
20.08.2013 07:54:48

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

1
14.12.2013 03:08:05

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

66
15.04.2015 15:44:55
Я делал скрипт контрольной суммы сеанса php, и большинство моих ключей были случайными строками [az09] ... Innodb потребовалось более 30 мс, INSERT ON DUPLICATE KEY UPDATEпоэтому я попробовал MyISAM, и теперь он меньше <1 мс ... Многие ответы, которые я видел, говорят, что Innodb трудно разобраться с «несортируемыми» (случайными строками) уникальными ключами ... Есть ли у вас какие-либо комментарии по этому поводу? На самом деле, я задавался вопросом о том, какое влияние это окажет на использование MyISAM, но ваш отличный ответ заставил меня понять, что это был путь для этого конкретного случая.
Louis Loudog Trottier 22.05.2017 05:56:17

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

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

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

3
14.03.2019 08:47:08

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

С точки зрения чистой скорости, 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) )

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

59
11.06.2015 09:15:31
производительность не всегда является единственным фактором, как насчет графика стабильности? двигатель не годится ни для чего, если он выходит из строя и не поддерживает базовые функции базы данных.
pilavdzice 2.05.2016 21:29:06
MyISAM, вероятно, будет бить InnoDB в большинстве случаев, если my.cnfфайл не оптимизирован для InnoDB. Вы не упомянули, как my.cnfвыглядит ваш файл, что действительно является наиболее важным фактором для производительности InnoDB.
itoctopus 16.11.2017 14:03:58
Спасибо, itoctopus - я хотел бы услышать больше о любых оптимизациях, которые вы рекомендуете. Полный код, использованный в этих тестах, приведен выше, не стесняйтесь повторять эксперименты с различными оптимизациями и дайте нам знать, если вы обнаружите значительные изменения в результатах
StackG 19.11.2017 17:25:47

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

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

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

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

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

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

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

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

2
8.06.2016 14:48:17
я не понизил голос, но если бы я сделал это, то для того, чтобы советовать никогда не использовать. слово никогда не должно быть зачеркнуто в словаре разработчика ... будьте осторожны, никогда не говори никогда.
hubson bropa 20.05.2016 17:07:18

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

Да, это история старых жен, что 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

24
5.06.2018 13:06:40
Усовершенствования технологии баз данных MySQL. А вопрос и ответы StackOverflow остаются в прошлом. В основных различиях между MyISAM и InnoDB являются менее о «нагрузке» на сервере, и более о поддержке ссылочной целостности и операциях , а также параллельности и возвратности (+10)
spencer7593 19.05.2017 01:58:32