MySQL перестроить индекс паузы на массовую вставку без транзакции - PullRequest
3 голосов
/ 10 апреля 2011

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

Есть ли способ заставить MySQL прекратить перестройку индексов для конкретной таблицы, пока я не скажу, что она может возобновиться?

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

Я не могу использовать INSERT DELAYED, так как мой тип таблицы - InnoDB. В противном случае INSERT DELAYED будет идеальным для меня.

Не то чтобы это важно, но я использую PHP / PDO для доступа к MySQL. Будем благодарны за любые советы, которые вы можете дать. Спасибо!

Ответы [ 2 ]

6 голосов
/ 02 сентября 2011
ALTER TABLE tableName DISABLE KEYS
// perform inserts
ALTER TABLE tableName ENABLE KEYS

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

Однако вы можете использовать множественные вставки (INSERT INTO table (...) VALUES (...), (...), (...), которые также будут обновлять индексы в пакетах.

3 голосов
/ 20 июня 2014

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

Например, для вставки пакета из 1000 строк используйте следующий SQL:

SET autocommit=0;
//Insert the rows one after the other, or using multi values inserts
COMMIT;

При отключении автоматической фиксации транзакция будет запущена с первого INSERT. Затем строки вставляются одна за другой, и в конце транзакция фиксируется и индексы перестраиваются.

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

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

...