Оптимизация импорта MySQL (преобразование подробного дампа SQL в быстрый / использование расширенных вставок)

Мы используем mysqldump с параметрами --complete-insert --skip-extended-insert для создания дампов базы данных, которые хранятся в VCS. Мы используем эти опции (и VCS), чтобы иметь возможность легко сравнивать разные версии баз данных.

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

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


person Alex    schedule 15.05.2013    source источник


Ответы (1)


Я написал небольшой скрипт на Python, который преобразует это:

LOCK TABLES `actor` WRITE;
/*!40000 ALTER TABLE `actor` DISABLE KEYS */;
INSERT INTO `actor` (`actor_id`, `first_name`, `last_name`, `last_update`) VALUES (1,'PENELOPE','GUINESS','2006-02-15 12:34:33');
INSERT INTO `actor` (`actor_id`, `first_name`, `last_name`, `last_update`) VALUES (2,'NICK','WAHLBERG','2006-02-15 12:34:33');
INSERT INTO `actor` (`actor_id`, `first_name`, `last_name`, `last_update`) VALUES (3,'ED','CHASE','2006-02-15 12:34:33');

в это:

LOCK TABLES `actor` WRITE;
/*!40000 ALTER TABLE `actor` DISABLE KEYS */;
INSERT INTO `actor` VALUES(1,'PENELOPE','GUINESS','2006-02-15 12:34:33'),(2,'NICK','WAHLBERG','2006-02-15 12:34:33'),(3,'ED','CHASE','2006-02-15 12:34:33');

Это не очень красиво или хорошо протестировано, но работает в тесте Sakila. дампы базы данных, поэтому он может обрабатывать нетривиальные файлы дампа.

В любом случае, вот сценарий:

#!/usr/bin/env python
# -*- coding: utf-8 -*- #

import re
import sys

re_insert = re.compile(r'^insert into `(.*)` \(.*\) values (.*);', re.IGNORECASE)

current_table = ''

for line in sys.stdin:
    if line.startswith('INSERT INTO'):
        m = re_insert.match(line)
        table = m.group(1)
        values = m.group(2)

        if table != current_table:
            if current_table != '':
                sys.stdout.write(";\n\n")
            current_table = table
            sys.stdout.write('INSERT INTO `' + table + '` VALUES ' + values)
        else:
            sys.stdout.write(',' + values)
    else:
        if current_table != '':
            sys.stdout.write(";\n")
            current_table = ''
        sys.stdout.write(line)

if current_table != '':
    sys.stdout.write(';')

Он ожидает ввода по конвейеру на стандартный ввод и выводит на стандартный вывод. Если бы вы сохранили скрипт как mysqldump-convert.py, вы бы использовали его так:

cat ./sakila-db/sakila-full-dump.sql | python mysqldump-convert.py > test.sql

Дайте мне знать, как вы поживаете!

person Duncan Lock    schedule 16.05.2013
comment
Красиво - спасибо! Я также создал операторы в DUMP, которые следует сохранить ... Я думаю, что мы должны обрабатывать только INSERT INTO - person Alex; 16.05.2013
comment
Я обновил скрипт, чтобы он пропускал строки без вставки, обрабатывал ввод из канала и правильно добавлял конечные точки с запятой. - person Duncan Lock; 16.05.2013
comment
Если этот ответ решит вашу проблему, не могли бы вы пометить его как принятый, чтобы другие пользователи могли видеть, что это ответ на вопрос? Спасибо! - person Duncan Lock; 17.05.2013
comment
Конечно, еще не проверял - проверю во вторник :-) Большое спасибо за ваши старания! - person Alex; 18.05.2013
comment
Итак, я протестировал скрипт и сделал две действительно незначительные правки - преобразование дампа базы данных с расширенными вставками и без них приводит после преобразования в идентичный дамп - идеально. Спасибо! - person Alex; 22.05.2013
comment
Я изменил preg (в PHP) на preg_match('/^insert into (.*) ([^)]*) values ​​(.*);/i', $line, $m); потому что оптимизация сломалась, когда поле содержало строковые значения - person Alex; 28.04.2015