MyISAM против InnoDB

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

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

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

Ответы

Ответ 1

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

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

                                                 MyISAM   InnoDB
----------------------------------------------------------------
Required full-text search                        Yes      5.6.4
----------------------------------------------------------------
Require transactions                                      Yes
----------------------------------------------------------------
Frequent select queries                          Yes      
----------------------------------------------------------------
Frequent insert, update, delete                           Yes
----------------------------------------------------------------
Row locking (multi processing on single table)            Yes
----------------------------------------------------------------
Relational base design                                    Yes

Подводя итог:

Frequent reading, almost no writing   => MyISAM
Full-text search in MySQL <= 5.5      => MyISAM

Во всех других случаях InnoDB обычно лучше всего подходит.

Ответ 2

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

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

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

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

Ответ 3

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

Попробуйте следующее:

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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

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

Но, конечно, тест.

Ответ 6

Немного поздно в игре... но здесь довольно полное сообщение

InnoDB - реляционная СУБД (RDBMS) и, следовательно, имеет ссылочную целостность, в то время как MyISAM этого не делает.

Сделки и атомарность

Данные в таблице управляются с помощью операторов языка манипулирования данными (DML), таких как SELECT, INSERT, UPDATE и DELETE. Группа транзакций состоит из двух или более операторов DML вместе в одну единицу работы, поэтому применяется либо весь блок, либо ни один из них.

MyISAM не поддерживает транзакции, в то время как InnoDB делает.

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

Если операция прервана при использовании таблицы InnoDB, поскольку она использует транзакции, которые имеют атомарность, любая транзакция, которая не переходит к завершению, не вступает в силу, поскольку фиксация не выполняется.

Столбиковая блокировка против блокировки строк

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

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

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

Сделки и откаты

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

Надежность

MyISAM не предлагает целостности данных. Аппаратные сбои, нечистые выключения и отмененные операции могут привести к повреждению данных. Это потребует полного ремонта или восстановления индексов и таблиц.

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

Индексирование FULLTEXT

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

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

Заключение

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

Ответ 7

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

С точки зрения чистой скорости, это не всегда так, что MyISAM быстрее, чем InnoDB, но по моему опыту он, как правило, быстрее работает в рабочих средах PURE READ примерно в 2,0-2,5 раза. Очевидно, что это не подходит для всех сред, как это написано другими, MyISAM не хватает таких операций, как транзакции и внешние ключи.

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

  • ВЫБОР ванили
  • отсчеты
  • условные SELECT
  • индексированные и неиндексированные подвыборы

Во-первых, я создал три таблицы, используя следующий SQL

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

с "MyISAM", замененным "InnoDB" и "памятью" во второй и третьей таблицах.

 

1) Vanilla выбирает

Запрос: SELECT * FROM tbl WHERE index_col = xx

Результат: draw

Comparison of vanilla selects by different database engines

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

Comparison of counts by different database engines

Это демонстрирует большую разницу между 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

Comparison of conditional selects by different database engines

Здесь 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 и вместо этого изменяю размер выбранных столбцов.

Comparison of sub-selects by different database engines

Здесь 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) )

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

Ответ 8

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

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

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

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

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

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

Ответ 9

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, могут занимать не более 8 000 байт. Для InnoDB нет полной индексации текста. В InnoDB COUNT (*) s (когда WHERE, GROUP BY или JOIN не используются) выполняются медленнее, чем в MyISAM, потому что количество строк не сохраняется внутри. InnoDB хранит данные и индексы в одном файле. InnoDB использует буферный пул для кэширования как данных, так и индексов.

MyISAM предлагает:

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

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

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

Ответ 10

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

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

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

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

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

Ответ 11

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

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

Ответ 12

MYISAM:

  • MYISAM поддерживает блокировку на уровне таблиц

  • MyISAM предназначен для скорости

  • MyISAM не поддерживает внешние ключи, поэтому мы называем MySQL с MYISAM СУБД
  • MyISAM хранит свои таблицы, данные и индексы в дисковом пространстве, используя отдельные три разных файла. (tablename.FRM, tablename.MYD, tablename.MYI)
  • MYISAM не поддерживает транзакцию. Вы не можете совершать и откатывать с помощью MYISAM. После того, как вы выполните команду, она будет выполнена.

INNODB:

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

Ответ 13

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

Мне особенно нравится (а также блокировка на уровне строк), что InnoDB основан на транзакциях, что означает, что вы можете обновлять/вставлять/создавать/изменять/удалять/etc несколько раз для одной "операции" вашего веб-приложения. Возникает проблема: если только некоторые из этих изменений/операций завершаются, а другие - нет, вы будете чаще всего (в зависимости от конкретного дизайна базы данных) в конечном итоге получить базу данных с конфликтующими данными/структурой.

Примечание.. В Oracle приложения create/alter/drop называются операторами DDL (Data Definition) и неявно запускают фиксацию. Операторы вставки/обновления/удаления, называемые "DML" (манипулирование данными), не выполняются автоматически, но только при выполнении DDL, фиксации или выхода/выхода (или если вы настроили сеанс на "автоматическую фиксацию" или если ваш клиент автоматически совершает транзакции). Обязательно знать об этом при работе с Oracle, но я не уверен, как MySQL обрабатывает два типа операторов. Из-за этого я хочу дать понять, что я не уверен в этом, когда дело доходит до MySQL; только с Oracle.

Пример, когда двигатели на основе транзакций превосходят:

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

В этом случае может быть таблица для гостей (имя, телефон, электронная почта и т.д.) и вторая таблица, которая отслеживает количество гостей, которые зарегистрировались. Таким образом, у нас есть две операции для одной "транзакции". Теперь предположим, что после того, как информация о гостях добавлена ​​в таблицу GUESTS, происходит потеря соединения или ошибка с тем же воздействием. Таблица GUESTS была обновлена ​​(вставлена ​​в), но соединение было потеряно до обновления "доступных мест".

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

Конечно, есть много способов справиться с этим, например, отслеживать доступные места с "100 минус количество строк в таблице гостей" или какой-то код, который проверяет соответствие информации и т.д. Но с движком базы данных на основе транзакций, таким как InnoDB, либо все операции выполняются, либо НИ ОДИН из них. Это может быть полезно во многих случаях, но, как я уже сказал, это не единственный способ быть в безопасности, нет (хороший способ, однако, обрабатывается базой данных, а не программистом / script -writer).

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

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

Наконец, примечание о блокировке таблицы и блокировке строк:

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я могу ошибаться во всем, что следует в отношении MySQL, и гипотетические/примерные ситуации - это вещи, которые нужно изучать, но я могу ошибаться в том, что именно можно вызвать коррупцию с MySQL. Однако примеры очень реальны в общем программировании, даже если у MySQL есть больше механизмов, чтобы избежать таких вещей...

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

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

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

  • Process one считывает текущее значение, допустим, оно пустое, таким образом, '0'.
  • Процесс два также считывает текущее значение, которое по-прежнему равно 0.
  • Обработает один файл (текущий + 1), который равен 1.
  • Процесс два должен записывать 2, но поскольку он считывает текущее значение перед тем, как процесс записывает новое значение, он также записывает 1 в таблицу.

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

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

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

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

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

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

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

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

Ответ 15

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

MariaDB

http://mariadb.org/

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

Сервер Percona

https://launchpad.net/percona-server

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

Ответ 16

MyISAM

MyISAM engine - это механизм по умолчанию в большинстве установок MySQL и является производным от исходного типа двигателя ISAM, который поддерживается в ранних версиях системы MySQL. Двигатель обеспечивает наилучшую комбинацию производительности и функциональности, хотя он не обладает возможностями транзакций (используйте механизмы InnoDB или BDB) и использует table-level locking.

Поддержка FlashMAX и FlashMAX: переход к трансформации Flash-платформы Скачать сейчас Если вам не нужны транзакции, существует несколько баз данных и приложений, которые невозможно эффективно сохранить с помощью механизма MyISAM. Тем не менее, очень высокопроизводительные приложения, в которых имеется большое количество вложений/обновлений данных по сравнению с количеством считываемых данных, могут вызвать пробоотборность производительности для механизма MyISAM. Первоначально он был разработан с идеей о том, что более 90% доступа к базе данных в таблице MyISAM будут считываться, а не записываться.

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

MyISAM Summary

Имя -MyISAM

Представлено -v3.23

Установка по умолчанию -Да

Ограничения по данным -Некоторые

Индексные ограничения -64 индексов на таблицу (32 до 4.1.2); Макс. 16 столбцов на индекс

Поддержка транзакций -No

Уровень блокировки -Table


InnoDB

InnoDB Engine предоставляется Innobase Oy и поддерживает все функциональные возможности базы данных (и многое другое) движка MyISAM, а также добавляет полные возможности транзакций (с полной совместимостью ACID (Atomicity, Consistency, Isolation и Durability) ) и блокировку данных на уровне строк.

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

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

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

InnoDB Summary

Имя -InnoDB

Введено -v3.23 (только исходный), v4.0 (исходный и двоичный)

Установка по умолчанию -Нет

Ограничения по данным -Некоторые

Ограничения индекса -Некоторые

Поддержка транзакций -Да (ACID-совместимый)

Уровень блокировки -Row

Ответ 17

По моему опыту, MyISAM был лучшим выбором, если вы не делаете DELETE, UPDATE, целый ряд одиночных INSERT, транзакций и полнотекстового индексирования. BTW, CHECK TABLE - ужасно. Поскольку таблица становится старше по количеству строк, вы не знаете, когда она закончится.

Ответ 18

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

Ответ 19

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

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

Ответ 20

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

Ответ 21

myisam - это NOGO для такого типа рабочей нагрузки (высокая запись concurrency), у меня нет такого большого опыта работы с innodb (протестировано 3 раза и найдено в каждом случае, что производительность сосала, но прошло некоторое время с тех пор, как последний тест) если вы не вынуждены запускать mysql, подумайте о том, чтобы дать postgres попробовать, поскольку он обрабатывает параллельные записи MUCH better

Ответ 22

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

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

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

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

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

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

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

P.S. Должен любить это, когда myISAM fanboys downvote, но не может сказать вам, какая часть этого ответа неверна.

Ответ 23

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

Ответ 24

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

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

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

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

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

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

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

Ответ 25

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

Ответ 26

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

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

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

Ответ 27

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

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

example: Я конвертировал файл 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).