Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
895
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4351
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
MyISAM против InnoDB
Я работаю над проектами, которые включают в себя много записей базы данных, я бы сказал ( 70% вставляет и 30% читает ). Это соотношение также будет включать обновления, которые я считаю одним чтением и одной записью. Чтение может быть грязным (например, мне не нужна 100% точная информация во время чтения).
Задача, о которой идет речь, будет заключаться в выполнении более 1 миллиона транзакций базы данных в час.
Я прочитал кучу материала в интернете о различиях между MyISAM и InnoDB, и MyISAM кажется мне очевидным выбором для конкретной базы данных/таблиц, которые я буду использовать для этой задачи. Из того, что я, кажется, читаю, InnoDB хорошо, если транзакции необходимы, так как поддерживается блокировка уровня строки.
Есть ли у кого-нибудь опыт работы с этим типом нагрузки (или выше)? Разве MyISAM-это правильный путь?
Я кратко обсудил этот вопрос в таблице, так что вы можете сделать вывод, стоит ли идти с InnoDB или MyISAM .
Вот небольшой обзор того, какой механизм хранения БД вы должны использовать в какой ситуации:
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 обычно является лучшим способом уйти.
Я не специалист по базам данных и говорю не по собственному опыту. Однако:
MyISAM таблицы используют блокировку на уровне таблиц . Исходя из Ваших оценок трафика, у вас есть около 200 записей в секунду. С MyISAM только один из них может быть запущен в любое время . Вы должны убедиться, что ваше оборудование может идти в ногу с этими транзакциями, чтобы избежать переполнения, т. е. один запрос может занять не более 5 мс.
Это наводит меня на мысль, что вам понадобится механизм хранения, который поддерживает блокировку на уровне строк, т. е. InnoDB.
С другой стороны, было бы довольно тривиально написать несколько простых сценариев для моделирования нагрузки с каждым механизмом хранения, а затем сравнить результаты.
Люди часто говорят о производительности, чтении и записи, внешних ключах и т. д. но есть еще одна обязательная функция для механизма хранения данных, на мой взгляд: атомарные обновления.
Попробовать это:
- Выдайте UPDATE против вашей таблицы MyISAM, которая занимает 5 секунд.
- В то время как UPDATE выполняется, скажем, через 2.5 секунд, нажмите Ctrl-C, чтобы прервать его.
- Наблюдайте за эффектами на столе. Сколько строк было обновлено? Сколько из них не были обновлены? Можно ли вообще читать таблицу, или она была повреждена, когда вы нажали Ctrl-C?
- Попробуйте проделать тот же эксперимент с UPDATE против таблицы InnoDB, прерывая выполнение запроса.
- Обратите внимание на таблицу InnoDB. Были обновлены нулевые строки. InnoDB заверил вас, что у вас есть атомарные обновления,и если полное обновление не может быть зафиксировано, он откатывает все изменения. Кроме того, таблица не повреждена. Это работает, даже если вы используете
killall -9 mysqldдля имитации сбоя.
Производительность, конечно, желательна, но не потеря данных должна превзойти это.
Я работал над высокообъемной системой, используя MySQL, и я пробовал как MyISAM, так и InnoDB.
Я обнаружил, что блокировка уровня таблицы в MyISAM вызвала серьезные проблемы с производительностью для нашей рабочей нагрузки, которая звучит так же, как и ваша. К сожалению, я также обнаружил, что производительность под InnoDB была также хуже, чем я надеялся.
В конце концов я решил проблему разногласий, фрагментировав данные таким образом, что вставки вошли в таблицу "hot" и selects никогда не запрашивали горячую таблицу.
Это также позволило удалениям (данные были чувствительны ко времени, и мы сохранили только X дней) происходить в таблицах "stale", которые снова не были затронуты запросами select. InnoDB, по-видимому, имеет низкую производительность при массовом удалении, поэтому, если вы планируете очистить данные, вы можете структурировать их таким образом, чтобы старые данные находились в устаревшей таблице, которую можно просто удалить вместо выполнения удаления на ней.
Конечно, я понятия не имею, что такое ваше приложение, но надеюсь, что это даст вам некоторое представление о некоторых проблемах с MyISAM и InnoDB.
Немного поздновато для game...but вот довольно полный пост, который я написал несколько месяцев назад, подробно описывая основные различия между MYISAM и InnoDB. Возьмите чашку чая (и, возможно, печенье) и наслаждайтесь.
Основное различие между MyISAM и InnoDB заключается в ссылочной целостности и транзакциях. Есть и другие отличия, такие как блокировка, откаты и полнотекстовый поиск.
ссылочная целостность
Ссылочная целостность гарантирует, что отношения между таблицами остаются согласованными. Более конкретно, это означает, что когда таблица (например, списки) имеет внешний ключ (например, Product ID), указывающий на другую таблицу (например, Products), когда обновления или удаления происходят в указанной таблице, эти изменения каскадируются в таблицу ссылок. В нашем примере, если продукт переименован, внешние ключи таблицы ссылок также будут обновлены; если продукт удален из таблицы "продукты", все списки, указывающие на удаленную запись, также будут удалены. Кроме того, любой новый листинг должен содержать этот внешний ключ, указывающий на действительную существующую запись.
InnoDB является реляционным DBMS (RDBMS) и, таким образом, имеет ссылочную целостность, в то время как MyISAM-нет.
Транзакции & Атомарность
Управление данными в таблице осуществляется с помощью операторов языка обработки данных (DML), таких как SELECT, INSERT, UPDATE и DELETE. Транзакция группирует два или более операторов DML вместе в одну единицу работы, поэтому применяется либо вся единица, либо ни одна из них.
MyISAM не поддерживает транзакции, в то время как InnoDB поддерживает.
Если операция прерывается при использовании таблицы MyISAM, она немедленно прерывается, и затронутые строки (или даже данные в каждой строке) остаются затронутыми, даже если операция не была завершена.
Если операция прерывается при использовании таблицы InnoDB, поскольку она использует транзакции, которые имеют атомарность, любая транзакция, которая не была завершена, не вступит в силу, так как фиксация не производится.
Блокировка таблицы против блокировки строк
Когда запрос выполняется к таблице MyISAM, вся таблица, в которой он запрашивает, будет заблокирована. Это означает, что последующие запросы будут выполняться только после завершения текущего запроса. Если Вы читаете большую таблицу и / или часто выполняете операции чтения и записи, это может означать огромное количество невыполненных запросов.
Когда запрос выполняется в отношении таблицы InnoDB, блокируются только соответствующие строки, а rest таблицы остается доступным для операций CRUD. Это означает, что запросы могут выполняться одновременно в одной и той же таблице при условии, что они не используют одну и ту же строку.
Эта функция в InnoDB называется параллелизмом. Как бы ни был велик параллелизм, существует серьезный недостаток, который применяется к выбранному диапазону таблиц, в том, что есть накладные расходы при переключении между потоками kernel, и вы должны установить ограничение на потоки kernel, чтобы предотвратить остановку сервера.
Транзакции & Откаты
Когда вы выполняете операцию в 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. Лучше всего перейти к хостинг-провайдеру, который поддерживает up-to-date версии MySQL. Нельзя сказать, что таблица MyISAM, использующая индексацию FULLTEXT, не может быть преобразована в таблицу InnoDB.
Вывод
В заключение, InnoDB должен быть выбранным механизмом хранения по умолчанию. Выберите MyISAM или другие типы данных, когда они служат определенной потребности.
Для загрузки с большим количеством операций записи и чтения, вы получите выгоду от InnoDB. Поскольку InnoDB обеспечивает блокировку строк, а не блокировку таблиц, ваши SELECT s могут быть параллельными, не только друг с другом, но и со многими INSERT s. однако, если вы не собираетесь использовать SQL транзакции, установите InnoDB commit flush в 2 ( innodb_flush_log_at_trx_commit ). Это дает вам много необработанной производительности, которую вы в противном случае потеряли бы при перемещении таблиц из MyISAM в InnoDB.
Кроме того, рассмотрите возможность добавления репликации. Это дает вам некоторое масштабирование чтения, и поскольку вы заявили, что ваши чтения не должны быть up-to-date, вы можете позволить репликации немного отстать. Просто будьте уверены, что он может догнать все, что угодно, кроме самого тяжелого трафика, или он всегда будет позади и никогда не догонит. Однако если вы идете этим путем, я настоятельно рекомендую вам изолировать чтение от подчиненных устройств и управление задержкой репликации для вашего обработчика базы данных. Это намного проще, если код приложения не знает об этом.
Наконец, следует учитывать различные нагрузки на таблицу. У вас не будет одинакового отношения чтения/записи для всех таблиц. Некоторые меньшие таблицы с почти 100% считыванием могли позволить себе остаться MyISAM. Аналогично, если у вас есть некоторые таблицы, которые находятся рядом с 100% write , вы можете воспользоваться INSERT DELAYED, но это поддерживается только в MyISAM (предложение DELAYED игнорируется для таблицы InnoDB).
Но я хочу быть уверенным в этом.
Чтобы добавить к широкому выбору ответов здесь, охватывающих механические различия между двумя двигателями,я представляю эмпирическое исследование сравнения скоростей.
Что касается чистой скорости, то не всегда получается, что MyISAM быстрее, чем InnoDB, но, по моему опыту, она имеет тенденцию быть быстрее для чистых рабочих сред чтения примерно в 2.0-2.5 раз. Очевидно, что это не подходит для всех сред - как писали другие, MyISAM не хватает таких вещей, как транзакции и внешние ключи.
Я сделал немного сравнительного анализа ниже - я использовал python для циклирования и библиотеку timeit для сравнения времени. Для интереса я также включил механизм памяти, это дает наилучшую производительность по всем направлениям, хотя он подходит только для небольших таблиц (вы постоянно сталкиваетесь с The table 'tbl' is full , когда превышаете лимит памяти MySQL). Четыре типа выбора, которые я рассматриваю, являются:
- ваниль SELECTs
- рассчитывает
- условный SELECTs
- индексированные и неиндексированные суб-выборки
Во-первых, я создал три таблицы, используя следующие 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
во второй и третьей таблицах вместо 'InnoDB' и 'memory' указано 'MyISAM'.
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 победы
Для этого запроса я создал дополнительный набор таблиц для поднабора. Каждый из них представляет собой просто два столбца BIGINTs, один с индексом первичного ключа и один без какого-либо индекса. Из-за большого размера таблицы я не тестировал механизм памяти. Команда создания таблицы SQL была
CREATE TABLE
subselect_myisam
(
index_col bigint NOT NULL,
non_index_col bigint,
PRIMARY KEY (index_col)
)
ENGINE=MyISAM DEFAULT CHARSET=utf8;
где во второй таблице снова вместо 'InnoDB' стоит 'MyISAM'.
В этом запросе я оставляю размер таблицы выбора равным 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) )
Я думаю, что главная идея всего этого заключается в том, что если вы действительно обеспокоены скоростью, вам нужно проверить запросы, которые вы делаете, а не делать какие-либо предположения о том, какой двигатель будет более подходящим.
Немного не по теме, но для целей документации и полноты я хотел бы добавить следующее.
В целом использование InnoDB приведет к гораздо более сложному приложению LESS, вероятно, также более свободному от ошибок. Поскольку вы можете поместить всю ссылочную целостность (ограничения внешнего ключа) в datamodel, вам не нужно даже близко столько кода приложения, сколько вам понадобится с MyISAM.
Каждый раз, когда вы вставляете, удаляете или заменяете запись, вы будете HAVE проверять и поддерживать отношения. E.g. если вы удаляете родителя, все дети также должны быть удалены. Например, даже в простой системе ведения блога, если вы удалите запись блогпостинга, вам придется удалить записи комментариев, лайки и т. д. В InnoDB это делается автоматически ядром СУБД (если вы указали ограничения в модели) и не требует никакого кода приложения. В MyISAM это должно быть закодировано в приложение, что очень сложно на веб-серверах. Веб-серверы по своей природе очень параллельны / параллельны, и поскольку эти действия должны быть атомарными и MyISAM не поддерживает никаких реальных транзакций, использование MyISAM для веб-серверов является рискованным / подверженным ошибкам.
Кроме того, в большинстве общих случаев InnoDB будет работать намного лучше по нескольким причинам, одна из которых заключается в возможности использовать блокировку уровня записи в отличие от блокировки уровня таблицы. Не только в ситуации, когда операции записи выполняются чаще, чем операции чтения, но и в ситуациях со сложными соединениями на больших наборах данных. Мы заметили увеличение производительности в 3 раза только за счет использования InnoDB таблиц над MyISAM таблицами для очень больших соединений (что занимает несколько минут).
Я бы сказал, что в целом InnoDB (использование модели данных 3NF в комплекте с ссылочной целостностью) должно быть выбором по умолчанию при использовании MySQL. MyISAM следует использовать только в очень специфических случаях. Это, скорее всего, будет работать меньше, приведет к большему и более глючному приложению.
Сказав это. Datamodelling-это искусство, которое редко встречается среди веб-дизайнеров / программистов. Не обижайтесь, но это объясняет, почему MyISAM так часто используется.
InnoDB предложения:
ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)
В InnoDB все данные в строке, кроме TEXT и BLOB, могут занимать не более 8000 байт. Полная текстовая индексация недоступна для InnoDB. В InnoDB COUNT (*) s (когда не используется WHERE, GROUP BY или JOIN) выполняется медленнее, чем в MyISAM, поскольку количество строк не хранится внутри системы. InnoDB хранит как данные, так и индексы в одном файле. InnoDB использует пул буферов для кэширования данных и индексов.
MyISAM предложения:
fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)
MyISAM имеет блокировку на уровне таблицы,но не на уровне строки. Никаких сделок. Нет автоматического восстановления после сбоя,но он предлагает функциональность таблицы восстановления. Никаких ограничений по внешнему ключу. MyISAM таблицы обычно имеют более компактный размер на диске по сравнению с InnoDB таблицами. MyISAM таблицы могут быть дополнительно сильно уменьшены в размере путем сжатия с помощью myisampack, если это необходимо, но становятся доступными только для чтения. MyISAM хранит индексы в одном файле и данные в другом. MyISAM использует буферы ключей для кэширования индексов и оставляет управление кэшированием данных операционной системе.
В целом я бы рекомендовал InnoDB для большинства целей и MyISAM только для специализированных применений. InnoDB теперь является двигателем по умолчанию в новых версиях MySQL.
Если вы используете MyISAM, вы не будете делать никаких транзакций в час, если только вы не считаете каждый оператор DML транзакцией (которая в любом случае не будет длительной или атомной в случае сбоя).
Поэтому я думаю, что вы должны использовать InnoDB.
300 транзакций в секунду-это довольно много. Если вам абсолютно необходимо, чтобы эти транзакции были долговечны при отключении питания, убедитесь, что ваша подсистема ввода-вывода может легко обрабатывать такое количество записей в секунду. Вам понадобится, по крайней мере, контроллер RAID с кэш-памятью на батарейках.
Если вы можете взять небольшой удар по долговечности, вы могли бы использовать InnoDB с innodb_flush_log_at_trx_commit, установленным в 0 или 2 (см. документы для деталей), вы можете улучшить производительность.
Есть ряд патчей, которые могут увеличить параллелизм от Google и других - они могут быть интересны, если вы все еще не можете получить достаточно производительности без них.
Этот вопрос и большинство ответов устарели .
Да, это старая бабья сказка, что MyISAM быстрее, чем InnoDB. обратите внимание на дату вопроса: 2008 год; сейчас почти десять лет спустя. С тех пор InnoDB добился значительных успехов в производительности.
Драматический график был для одного случая, когда выигрывает MyISAM: COUNT(*) без предложения WHERE . Но разве именно на это вы тратите свое время?
Если вы запустите тест параллелизма , то InnoDB с большой вероятностью выиграет, даже против MEMORY .
Если вы делаете какие-либо записи во время бенчмаркинга SELECTs , MyISAM и MEMORY , скорее всего, проиграют из-за блокировки уровня таблицы.
На самом деле, Oracle настолько уверен, что InnoDB лучше, что они почти удалили MyISAM из 8.0.
Этот вопрос был написан в начале 1933 года. С тех пор эти основные версии были помечены как " общедоступные":
- 2010: 5.5 (.8 декабря.)
- 2013: 5.6 (.10 февраля.)
- 2015: 5.7 (.9 октября.)
- 2018: 8.0 (.11 апреля.)
Итог: Не используйте MyISAM
Пожалуйста, обратите внимание, что мое формальное образование и опыт работы с Oracle, в то время как моя работа с MySQL была полностью личной и в мое личное время, так что если я говорю вещи, которые верны для Oracle, но не верны для MySQL, я приношу свои извинения. Хотя эти две системы имеют много общего, реляционная теория / алгебра одна и та же, и реляционные базы данных все еще являются реляционными базами данных, все еще есть много различий!!
Мне особенно нравится (а также блокировка на уровне строк), что InnoDB основан на транзакциях, а это означает, что вы можете быть updating/inserting/creating/altering/dropping/etc несколько раз для одного "operation" вашего веб-приложения. Проблема заключается в том, что если только некоторые из этих изменений/операций будут зафиксированы, а другие нет, то в большинстве случаев (в зависимости от конкретной конструкции базы данных) вы получите базу данных с конфликтующими data/structure.
Примечание: В случае Oracle операторы create/alter/drop называются операторами "DDL" (определение данных) и неявно инициируют фиксацию. Операторы Insert/update/delete, называемые "DML" (манипуляция данными), не фиксируются автоматически, но только при выполнении DDL, commit или exit/quit (или если вы устанавливаете сеанс на "автокоммит", или если ваш клиент автокоммит). Это очень важно знать при работе с Oracle, но я не уверен, как MySQL обрабатывает два типа утверждений. Поэтому я хочу дать вам понять, что я не уверен в этом, когда речь заходит о MySQL; только с Oracle.
Пример сделки на основе двигателей excel:
Предположим, что я или вы находитесь на веб-странице, чтобы зарегистрироваться на бесплатное мероприятие, и одна из основных целей системы заключается в том, чтобы разрешить только до 100 человек зарегистрироваться, так как это предел мест для проведения мероприятия. После достижения 100 подписок система отключит дальнейшие регистрации, по крайней мере до тех пор, пока другие не отменят их.
В этом случае может быть стол для гостей (имя, телефон, email и т.д.).), и второй стол, который отслеживает количество гостей, которые зарегистрировались. Таким образом, мы имеем две операции для одного "transaction". Теперь предположим, что после добавления гостевой информации в таблицу GUESTS происходит потеря соединения или ошибка с тем же результатом. Таблица GUESTS была обновлена (вставлена в нее), но соединение было потеряно до обновления таблицы "available seats".
Теперь у нас есть гость, добавленный к гостевому столу, но количество доступных мест теперь неверно (например, значение равно 85, когда на самом деле 84).
Конечно , есть много способов справиться с этим, например, отслеживать доступные места с помощью "100 minus number of rows in guests table," или какого-то кода, который проверяет, что информация непротиворечива, и т. д.... Но при использовании механизма баз данных на основе транзакций, такого как InnoDB, фиксируется либо ALL из операций, либо NONE из них. Это может быть полезно во многих случаях, но, как я уже сказал, это не ONLY способ быть безопасным, нет (хороший способ, однако, обрабатывается базой данных, а не programmer/script-writer).
Вот и все, что "transaction-based" по существу означает в этом контексте, если только я чего-то не упускаю-что либо вся транзакция проходит успешно, как и должна, либо ничего не меняется, так как внесение только частичных изменений может внести незначительный беспорядок в базу данных SEVERE, возможно даже испортить ее...
Но я повторю еще раз, это не единственный способ избежать беспорядка. Но это один из методов, который обрабатывает сам движок, оставляя вас в коде / скрипте с единственной необходимостью беспокоиться о том," была ли транзакция успешной или нет, и что мне делать, если нет (например, повторная попытка)", вместо того чтобы вручную писать код для проверки его "manually" из-за пределов базы данных и делать намного больше работы для таких событий.
Наконец, заметка о блокировке таблиц против блокировки строк:
DISCLAIMER: я могу ошибаться во всем, что следует в отношении MySQL, и гипотетические/примерные ситуации-это вещи, которые нужно рассмотреть, но я могу ошибаться в том, что именно может вызвать коррупцию с MySQL. Однако эти примеры весьма реальны в общем программировании, даже если MySQL имеет больше механизмов, чтобы избежать таких вещей...
Во всяком случае, я вполне уверен, что соглашусь с теми, кто утверждал, что количество разрешенных соединений за один раз не работает вокруг заблокированного стола. На самом деле, несколько соединений-это весь смысл блокировки таблицы! ! Таким образом, другие processes/users/apps не могут повредить базу данных, внося изменения одновременно.
Как два или более соединений, работающих в одном ряду, могут сделать для вас действительно плохой день?? Предположим, что есть два процесса, которые хотят / должны обновить одно и то же значение в одной строке, скажем, потому что строка является записью автобусного тура, и каждый из двух процессов одновременно хочет обновить поле "riders" или "available_seats" как "the current value plus 1."
Давайте сделаем это гипотетически, шаг за шагом:
- Процесс Один читает текущее значение, допустим, оно пустое, таким образом, '0' пока что.
- Процесс два также считывает текущее значение, которое по-прежнему равно 0.
- Процесс один пишет (текущий + 1), который равен 1.
- Процесс два должен записывать 2, но так как он считывает текущее значение до того, как процесс один запишет новое значение, он также записывает 1 в таблицу.
Я не уверен , что две связи могут так перемешаться, и обе читают до того, как первая пишет... Но если нет, то я все равно вижу проблему с:
- Процесс один считывает текущее значение, которое равно 0.
- Процесс один записывает (текущий + 1), что равно 1.
- Теперь процесс два считывает текущее значение. Но в то время как процесс one DID write (update) не зафиксировал данные, таким образом, только тот же самый процесс может прочитать новое значение, которое он обновил, в то время как все остальные видят более старое значение, пока не произойдет фиксация.
Кроме того, по крайней мере, с базами данных Oracle существуют уровни изоляции, которые я не буду тратить наше время, пытаясь перефразировать. Вот хорошая статья на эту тему, и каждый уровень изоляции имеет свои плюсы и минусы, которые будут идти вместе с тем, насколько важными могут быть механизмы на основе транзакций в базе данных...
Наконец, вполне вероятно, что в рамках MyISAM вместо внешних ключей и взаимодействия на основе транзакций будут действовать другие гарантии. Ну, во-первых, есть тот факт, что вся таблица заблокирована, что делает менее вероятным, что транзакции/FKs необходимы .
И увы, если вы знаете об этих проблемах параллелизма, да, вы можете играть в нее менее безопасно и просто писать свои приложения, настраивать свои системы так, чтобы такие ошибки были невозможны (тогда ваш код несет ответственность, а не сама база данных). Однако, на мой взгляд, я бы сказал, что всегда лучше использовать как можно больше защитных мер, программируя оборонительно и всегда осознавая, что полностью избежать человеческой ошибки невозможно. Это случается со всеми, и любой, кто говорит, что он невосприимчив к этому, должно быть, лжет или не сделал больше, чем написал "Hello World" application/script. ;-)
Я надеюсь, что SOME из этого кому-то полезно, и даже больше-так, я надеюсь, что я только что не был виновником предположений и не был человеком в заблуждении!! Приношу свои извинения, если это так, но примеры хороши для размышления, исследования риска и так далее, Даже если они не являются потенциальными в этом конкретном контексте.
Не стесняйтесь поправлять меня, редактировать этот "answer," и даже голосовать за него. Просто, пожалуйста, попытайтесь улучшить, а не исправлять мое плохое предположение с другим. ;-)
Это мой первый ответ, поэтому, пожалуйста, простите длину из-за всех отказов и т. д... Я просто не хочу показаться высокомерным, когда я не совсем уверен!
Я думаю, что это отличная статья о том, как объяснить различия и когда вы должны использовать одно над другим: http://tag1consulting.com/MySQL_Engines_MyISAM_vs_InnoDB
Кроме того, проверить некоторые падени-в замене для себя MySQL :
MariaDB
MariaDB-это сервер базы данных, обеспечивающий понижение функциональности замены для MySQL. MariaDB построен некоторыми оригинальными авторами MySQL, при содействии более широкого сообщества разработчиков свободного и открытого программного обеспечения. В дополнение к основной функциональности MySQL, MariaDB предлагает богатый набор улучшений функций, включая альтернативные механизмы хранения, оптимизацию серверов и исправления.
Фирконом Сервера
https://launchpad.net/percona-server
Улучшенная замена drop-in для MySQL, с лучшей производительностью, улучшенной диагностикой и дополнительными функциями.
Я выяснил, что даже при том, что Myisam имеет конфликт блокировки, он все равно быстрее, чем InnoDb в большинстве сценариев из-за быстрой схемы получения блокировки, которую он использует. Я пробовал несколько раз Innodb и всегда возвращался к MyIsam по той или иной причине. Кроме того, InnoDB может быть очень интенсивным CPU при огромных нагрузках на запись.
Каждое приложение имеет свой собственный профиль производительности для использования базы данных, и есть вероятность, что он будет меняться с течением времени.
Самое лучшее, что вы можете сделать, это проверить свои возможности. Переключение между MyISAM и InnoDB тривиально, поэтому загрузите некоторые тестовые данные и запустите jmeter против вашего сайта и посмотрите, что произойдет.
myisam-это NOGO для такого типа рабочей нагрузки (высокий параллелизм записи), у меня нет такого большого опыта работы с innodb (протестировал его 3 раза и обнаружил в каждом случае, что производительность отстой, но это было некоторое время с момента последнего теста) если вас не заставляют запускать mysql, попробуйте использовать postgres, так как он лучше обрабатывает параллельные записи MUCH
Короче говоря, InnoDB-это хорошо, если вы работаете над чем-то, что нуждается в надежной базе данных, которая может обрабатывать множество инструкций INSERT и UPDATE.
и, MyISAM хорошо, если вам нужна база данных, которая в основном будет принимать много инструкций чтения (SELECT), а не записи (INSERT и UPDATES), учитывая ее недостаток в том, что она блокирует таблицу.
возможно, вы захотите проверить это;
Плюсы и минусы InnoDB
Плюсы и минусы MyISAM
Я знаю, что это не будет популярно, но вот идет:
myISAM не поддерживает основные элементы базы данных, такие как транзакции и ссылочная целостность, что часто приводит к сбоям / ошибкам приложений. Вы не можете не изучить правильные основы проектирования баз данных, если они даже не поддерживаются вашим ядром БД.
Отказ от использования ссылочной целостности или транзакций в мире баз данных подобен отказу от использования объектно-ориентированного программирования в мире программного обеспечения.
InnoDB существует сейчас, используйте его вместо этого! Даже разработчики MySQL в конце концов уступили, чтобы изменить это на движок по умолчанию в более новых версиях, несмотря на то, что myISAM был оригинальным движком, который был по умолчанию во всех устаревших системах.
Нет, это не имеет значения, если Вы читаете или пишете, или какие у вас есть соображения производительности, использование myISAM может привести к целому ряду проблем, таких как эта, с которой я только что столкнулся: я выполнял синхронизацию базы данных и в то же время кто-то другой обращался к приложению, которое обращалось к таблице, установленной на myISAM. Из-за отсутствия поддержки транзакций и вообще плохой надежности этого движка, это привело к краху всей базы данных, и мне пришлось вручную перезапустить mysql!
За последние 15 лет разработки я использовал множество баз данных и движков. myISAM обрушивался на меня около десятка раз за этот период, другие базы данных-только один раз! И это была база данных microsoft SQL, где какой - то разработчик написал ошибочный код CLR (common language runtime-в основном код C#, который выполняется внутри базы данных), кстати, это была не совсем ошибка компонента database engine.
Я согласен с другими ответами здесь, которые говорят, что качественные высокодоступные, высокопроизводительные приложения не должны использовать myISAM, поскольку он не будет работать, он не является достаточно надежным или стабильным, чтобы привести к безысходному опыту. Более подробную информацию смотрите в ответе Билла Карвина.
P.S. Мне очень нравится, когда myISAM fanboys понижают голос, но не могут сказать вам, какая часть этого ответа неверна.
Для этого соотношения чтения / записи я бы предположил, что InnoDB будет работать лучше. Так как вы прекрасно справляетесь с грязными чтениями, вы можете (если вы позволите себе) реплицироваться на раба и позволить всем вашим чтениям перейти к рабу. Кроме того, подумайте о том, чтобы вставлять сразу несколько записей, а не по одной.
Почти каждый раз, когда я начинаю новый проект, я гуглю один и тот же вопрос, чтобы узнать, есть ли у меня новые ответы.
В конечном итоге все сводится к тому, что я беру последнюю версию MySQL и запускаю тесты.
У меня есть таблицы, где я хочу сделать поиск ключей/значений... и это все. Мне нужно получить значение (0-512 байта) для ключа hash. Там не так много сделок на этом DB. Таблица периодически получает обновления (в полном объеме), но 0 транзакций.
Таким образом, мы здесь говорим не о сложной системе, а о простом поиске.. и как (кроме того, чтобы сделать таблицу RAM резидентной) мы можем оптимизировать производительность.
Я также провожу тесты на других базах данных (т. е. NoSQL), чтобы увидеть, есть ли где-нибудь, где я могу получить преимущество. Самое большое преимущество, которое я нашел, заключается в сопоставлении ключей, но что касается поиска, то MyISAM в настоящее время возглавляет их все.
Хотя я бы не стал выполнять финансовые операции с таблицами MyISAM, но для простых поисков вы должны проверить это.. обычно от 2x до 5x queries/sec.
Испытайте это, я приветствую дебаты.
bottomline: если вы работаете в автономном режиме с выделениями на больших кусках данных, 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).