Оптимизировать массивные вставки MySQL - PullRequest
1 голос
/ 15 сентября 2010

У меня есть приложение, которое должно запускать ежедневный скрипт; ежедневный сценарий состоит в загрузке файла CSV с 1 000 000 строк и вставке этих строк в таблицу.

Я размещаю свое приложение в Dreamhost. Я создал цикл while, который проходит по всем строкам CSV и выполняет запрос INSERT для каждого из них. Дело в том, что я получаю «500 Internal Server Error». Даже если я разберу его в 1000 файлов по 1000 строк в каждом, я не смогу вставить более 40 или 50 тысяч строк в один цикл.

Есть ли способ оптимизировать ввод? Я также рассматриваю возможность использования выделенного сервера; что ты думаешь?

Спасибо!

Pedro

Ответы [ 10 ]

13 голосов
/ 15 сентября 2010

Большинство баз данных имеют оптимизированный процесс массовой вставки - MySQL - это синтаксис LOAD DATA FILE .

Чтобы загрузить файл CSV, используйте:

LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\r\n'
  IGNORE 1 LINES;
6 голосов
/ 15 сентября 2010

Вставьте несколько значений вместо

insert into table values(1,2);

до

insert into table values (1,2),(2,3),(4,5);

До соответствующего количества строк одновременно.

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

http://dev.mysql.com/doc/refman/5.0/en/load-data.html

3 голосов
/ 15 сентября 2010

Обычно я бы сказал, просто используйте LOAD DATA INFILE, но, похоже, вы не можете использовать вашу среду общего хостинга.

Я не использовал MySQL в течение нескольких лет, но у них есть очень хороший документ, который описывает, как ускорить вставки для массовых вставок: http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

Несколько идей, которые можно почерпнуть из этого:

  • Отключение / включение клавиш вокруг вставок:

    ALTER TABLE tbl_name DISABLE KEYS; ALTER TABLE tbl_name ENABLE KEYS;

  • Используйте много значений в ваших операторах вставки.

    Т.е.: INSERT INTO таблица (col1, col2) VALUES (val1, val2), (.., ..), ...

    Если я правильно помню, вы можете иметь до 4096 значений на оператор вставки.

  • Запустите команду FLUSH TABLES еще до запуска, чтобы убедиться, что нет ожидающих операций записи на диск, которые могут снизить производительность вставки.

Я думаю, что это сделает все быстро. Я бы предложил использовать LOCK TABLES, но я думаю, что отключение клавиш делает это спорным.

UPDATE

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

  • Обеспечение отсутствия в вашей таблице данных, которые "сталкиваются" с новыми загружаемыми данными (если вы начинаете с нуля, здесь будет полезен оператор TRUNCATE).
  • Написание скрипта для очистки ваших входных данных, чтобы избежать дублирования локально. В любом случае, проверка на наличие дубликатов может стоить вам много времени.
  • Если вы сделаете это, ENABLE KEYS не должен завершиться ошибкой.
0 голосов
/ 10 апреля 2014

Перейдите в phpmyadmin и выберите таблицу, в которую вы хотите вставить.

На вкладке «Операции», а затем в разделе / ​​разделе «Параметры таблицы» измените механизм хранения с InnoDB на MyISAM.

Однажды у меня была похожая проблема.Хорошо провести время.

0 голосов
/ 05 августа 2011

Было бы лучше, если вы используете sqlloader. Вам понадобятся две вещи: первый управляющий файл, который определяет действия, которые должен выполнять SQL Loader, и второй файл CSV, который вы хотите загрузить. Вот ссылка ниже, которая поможет вам. http://www.oracle -dba-online.com / sql_loader.htm

0 голосов
/ 15 сентября 2010

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

Я обнаружил, чтов моей ситуации я не мог MySQL принять один большой оператор INSERT, но обнаружил, что, если я разделю его на группы по 10 000 INSERTS за раз, например, как предложено в nos, тогда он выполнит свою работу довольно быстро.Стоит отметить, что при выполнении нескольких таких операций INSERT вы, скорее всего, достигнете предела времени ожидания PHP, но этого можно избежать, сбросив тайм-аут с помощью set_time_limit ($ секунд) , я обнаружил, что делать это послекаждый успешный INSERT работал очень хорошо.

Вы должны быть осторожны с этим, потому что вы можете оказаться в цикле аварии с неограниченным тайм-аутом, и для этого я бы предложил протестировать, чтобы убедиться, что каждый INSERT былуспешным путем проверки ошибок, о которых сообщает MySQL, с помощью mysql_errno () или mysql_error () .Вы также можете перехватывать ошибки, проверяя количество строк, на которые влияет INSERT, с помощью mysql_affered_rows () .После этого вы можете остановиться после первой ошибки.

0 голосов
/ 15 сентября 2010

Вы пытались делать транзакции?Просто отправьте команду BEGIN в MySQL, сделайте все ваши вставки, затем выполните COMMIT.Это значительно ускорило бы его, но, как сказал Касабланка, ваш сценарий, вероятно, также истекает.

0 голосов
/ 15 сентября 2010

Предложение OMG Ponies отличное, но я также «вручную» отформатировал данные в том же формате, который использует mysqldump, а затем загрузил их таким образом.Очень быстро.

0 голосов
/ 15 сентября 2010

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

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

0 голосов
/ 15 сентября 2010

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

Таким образом, вы можете добавить столько строк, сколько вам нужно.

Если у вас есть выделенный сервер, это будет проще,Вы просто запускаете цикл со всеми запросами на вставку.

Конечно, вы можете попытаться установить для time_limit значение 0 (если оно работает на Dreamhost) или увеличить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...