У меня есть таблица MyISAM с двумя полями f1 и f2, как целыми, так и незанятыми, и не может быть нулевым. Таблица преднамеренно не имеет первичного ключа, но имеет индекс на f2. В таблице в настоящее время содержится 320 миллионов строк.
Я хотел бы иметь возможность вставлять новые строки (около 4000 раз в неделю) в эту таблицу с приличной скоростью. Однако в настоящее время я вставляю около 4000 строк за 2 минуты. (Я делаю это, используя текстовый файл и команду "source" - текстовый файл содержит только инструкции INSERT в этой таблице). Есть ли способ ускорить высказывания вставки? Кроме того, во время выполнения инструкций INSERT будут ли затронуты или замещены какие-либо операторы SELECT/JOIN в одну и ту же таблицу?
Вы можете разгружать инструкции вставки из
INSERT INTO table (f1, f2) VALUES ($f1, $f2);
INSERT INTO table (f1, f2) VALUES ($other, $other);
etc...
в
INSERT INTO table (f1, f2) VALUES ($f1, $f2), ($other, $other), etc...
что несколько уменьшит количество надписей. Это может немного ускорить процесс. Однако не заходите слишком далеко за борт, группируя вставки, поскольку запрос подчиняется настройке max_allowed_packet
.
4000 строк за 2 минуты все еще 33 строки в секунду. Это не слишком потрепанный, особенно на огромной таблице, где индекс должен быть обновлен. Вы можете отключить ключи в таблице перед выполнением вставки, а затем снова восстановить ключ с помощью REPAIR TABLE
, но это может занять больше времени, особенно с 320 миллионами строк для сканирования. Вам нужно будет провести бенчмаркинг, чтобы убедиться, что это достойно.
Что касается SELECTS/JOINS, так как вы находитесь на таблицах MYISAM, нет способа скрыть новые таблицы в транзакции, пока они не будут выполнены. Каждая строка сразу будет видна для другого сеанса по мере его ввода, если вы не заблокируете таблицу, чтобы получить эксклюзивный доступ к ней для вставок. Но тогда вы заблокировали всех остальных во время работы вставки.
LOAD DATA INFILE
@rjk корректно. LOAD DATA INFILE - это самый быстрый способ получить данные в вашей таблице. Мало других мыслей.
Мне кажется, 2 минуты для строк 4k. SELECT блокируют INSERT в MyISAM и, вероятно, замедляют ваши вставки. Я настоятельно рекомендую InnoDB, у которого нет этой проблемы, плюс лучшее восстановление после сбоя и т.д. Если вы должны использовать MyISAM, блокировка таблицы перед запуском ваших вставок может помочь или вы можете попробовать INSERT DELAYED, которая позволит операциям INSERT немедленно возвращаться и быть обрабатывается, когда таблица свободна.
Если для загрузки данных можно получить доступ к базе данных, вы можете использовать команду LOAD DATA INFILE. Как описано в руководстве:
Оператор LOAD DATA INFILE читает строки из текстового файла в таблицу на очень высокая скорость.
Надеюсь, что это поможет.
Насколько я знаю, команда source
- это самый быстрый способ сделать это. Поскольку таблица MyISAM, вся таблица блокируется во время действий записи. Поэтому да, все SELECT
-statements помещаются в очередь до тех пор, пока все вставки/обновления/удаления не закончатся.