Копирование большого объёма данных из одной таблицы в другую

Есть два таблицы: pos, temp_pos. В первой таблице содержится немногим более 350 млн записей, во второй около 3 млн записей. Требуется максимально эффективно перенести данные из одной таблицы в другую. Интересует вот какие моменты:
1. Какой движок для этой задачи лучше подойдёт InnoDB или всё же MyISAM?
2. Требуется ли отключать проверку ключей и включать её после? Ускоряет ли это процесс или наоборот замедляет?

Сейчас я делаю это так:
ALTER TABLE pos DISABLE KEYS;
INSERT INTO pos (id, position, url_id, dataset_id) SELECT id, position, url_id, dataset_id from temp_pos;
ALTER TABLE pos ENABLE KEYS;

Сейчас используется MyISAM и операция переноса данных занимает в среднем от 40 минут до 2.5 часа. Хочется делать это максимально эффективно.
  • Вопрос задан
  • 9352 просмотра
Пригласить эксперта
Ответы на вопрос 6
xytop
@xytop
PHP/RoR web dev & tech lead
MyISAM для вставок должен быть побыстрее чем InnoDB ( www.opennet.ru/tips/info/1958.shtml )

попробуйте такой метод:
SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET SESSION tx_isolation='READ-UNCOMMITTED';
SET sql_log_bin = 0;
ALTER TABLE pos DISABLE KEYS;

INSERT INTO pos (id, position, url_id, dataset_id) SELECT id, position, url_id, dataset_id from temp_pos;

ALTER TABLE pos ENABLE KEYS;
SET sql_log_bin = 1;
SET UNIQUE_CHECKS = 1;
SET FOREIGN_KEY_CHECKS = 1;
SET SESSION tx_isolation='READ-REPEATABLE';
Ответ написан
KEKSOV
@KEKSOV
На офсайте есть много полезного на эту тему. И Google по запросу mysql speedup insert select может помочь

Если будете использовать InnoDB, то добавьте в заголовок еще SET autocommit=0; а после инсерта добавьте COMMIT;
Ответ написан
Комментировать
@edogs
Доступ к ФС есть?
Если да. то
а) Можно скопировать файлы баз данных (myd,frm,myi), предварительно остановив БД.
б) Можно воспользоваться mysqlhotcopy (делает почти то же что пункт А, только умнее и не останавливая всю БД).

p.s.: Если данные из одной таблицы в другую надо именно добавлять, тогда вышеописанное годится для «выброса» данных из рабочей таблицы во временную, что бы рабочая уже дальше работала пока идет долгое копирование через insert into
Ответ написан
Комментировать
wartur
@wartur
В InnoDB можно включить транзакцию и все записать в один раз, тогда оптимизируется работа журнала и повышается скорость. Отключение внешних ключей тоже ускорит скорость, но так надо делать если вы уверены в своих действиях.
Ответ написан
Комментировать
@Vampiro
В первой таблице содержится около 3 млн записей, во второй немногим более 350 млн записей

Мне кажется, выгоднее переименовать таблицы, поменяв их местами. Вставлять 3 проще, чем 350. Если же вам необходимо постоянно гонять 350кк записей из таблицы в таблицу — вероятно у вас что-то не так с архитектурой, и следует подумать в сторону триггеров или чего-то кеширующего по дороге от данных к мускулю. Вроде мемкеш сейчас делают простенькую бд, но я тут не владею информацией. надо смотреть по приложению — куда складывать.
Ответ написан
@balloon
У нас похожие задачи с сравнимым объемом данных. SELECT + LOAD на InnoDB занимает минуты (SSD + ~120Gb RAM). Ключи не отключаем, как и autocommit - имхо при атомарных запросах смысла в этом нет, индексы и так будут обновлены только после окончания записи всех данных. Делаем LOAD IGNORE что бы игнорить дубликаты. Еще одно переимущество SELECT + LOAD перед SELECT INSERT - отсутствие блокировки на время SELECT.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы