улучшить скорость импорта mysql

У меня большая база данных 22GB. Раньше я делал резервную копию командой mysqldump в формате gzip.

Когда я извлекаю файл gz, он создает .sql файл 16.2GB

Когда я пытаюсь импортировать базу данных на свой локальный сервер, импорт занимает около 48 часов. Есть ли способ увеличить скорость процесса импорта?

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

Текущая конфигурация системы

 Processor: 4th Gen i5
 RAM: 8GB

#update

my.cnf выглядит следующим образом

#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
#
# * Basic Settings
#
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address        = 127.0.0.1
#
# * Fine Tuning
#
key_buffer      = 16M
max_allowed_packet  = 512M
thread_stack        = 192K
thread_cache_size       = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover         = BACKUP
#max_connections        = 100
#table_cache            = 64
#thread_concurrency     = 10
#
# * Query Cache Configuration
#
query_cache_limit   = 4M
query_cache_size        = 512M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file        = /var/log/mysql/mysql.log
#general_log             = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
#log_slow_queries   = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
#server-id      = 1
#log_bin            = /var/log/mysql/mysql-bin.log
expire_logs_days    = 10
max_binlog_size         = 100M
#binlog_do_db       = include_database_name
#binlog_ignore_db   = include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem



[mysqldump]
quick
quote-names
max_allowed_packet  = 512M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completition

[isamchk]
key_buffer      = 512M

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/

Он загружается в течение 3 дней, и сейчас импортировано 9,9 ГБ. В базе данных есть таблицы MyISAM и InnoDB. Что я могу сделать, чтобы повысить производительность импорта?

Я пробовал экспортировать каждую таблицу отдельно в формате gz с mysqldump и импортировать каждую таблицу через скрипт PHP, выполняя следующий код

$dir="./";
$files = scandir($dir, 1);
array_pop($files);
array_pop($files);
$tablecount=0;
foreach($files as $file){
    $tablecount++;
    echo $tablecount."     ";

    echo $file."\n";
    $command="gunzip < ".$file." | mysql -u root -pubuntu cms";

    echo exec($command);
}

person dharanbro    schedule 15.04.2015    source источник
comment
Можете ли вы принять, что сервер mysql отключен на несколько секунд? Если можете, сделайте резервную копию файлов базы данных mysql напрямую и просто скопируйте их обратно при восстановлении. Обе операции требуют, чтобы сервер mysql был отключен. Это небезопасный, но эффективный способ.   -  person Frederick Zhang    schedule 22.04.2015
comment
сколько у вас столов?   -  person Alex    schedule 22.04.2015
comment
Вы можете добавить дополнительную информацию о проблеме - это узкое место ЦП или диска, это конкретная таблица, вызывающая медленный импорт; если да, то какова структура таблицы, сколько в ней строк и т. д.   -  person VolenD    schedule 23.04.2015
comment
@Alex у меня 204 стола   -  person dharanbro    schedule 23.04.2015
comment
У нас было несколько больших таблиц (10 ГБ), и для MySQL это было слишком много для импорта / экспорта. Помогло перемещение больших таблиц журналов в MongoDB. Я знаю, что это не решит вашу проблему, но однажды вам может потребоваться принять решение.   -  person Zdenek Machek    schedule 26.04.2015
comment
Возможный дубликат stackoverflow.com/a/2167641/763468   -  person Steve Robbins    schedule 29.04.2015
comment
Вы также можете выборочно выгружать таблицы. Если есть какие-либо таблицы журнала / кеша, которые вам не нужны локально, исключите их из своего mysqldump.   -  person Steve Robbins    schedule 29.04.2015


Ответы (9)


Многие параметры отсутствуют, чтобы полностью понять причину проблемы. Такие как:

  1. Версия MySQL
  2. Тип и скорость диска
  3. Освободите память на сервере перед запуском сервера MySQL
  4. Вывод iostat до и во время mysqldump.
  5. Какие параметры вы используете в первую очередь для создания файла дампа.

и многое другое.

Поэтому я попытаюсь угадать, что ваша проблема в дисках, потому что у меня есть 150 экземпляров MySQL, которыми я управляю с 3 ТБ данных на одном из них, и обычно проблема заключается в диске.

Теперь к решению:

Прежде всего - ваш MySQL не настроен для лучшей производительности.

Вы можете прочитать о наиболее важных настройках в блоге Percona: http://www.percona.com/blog/2014/01/28/10-mysql-settings-to-tune-after-установка/

Особенно проверьте параметры:

innodb_buffer_pool_size 
innodb_flush_log_at_trx_commit
innodb_flush_method

Если ваша проблема в диске - чтение файла с того же диска усугубляет проблему.

И если ваш сервер MySQL начинает менять местами из-за того, что ему не хватает оперативной памяти, ваша проблема становится еще больше.

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

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

Это Percona Xtrabackup - ​​http://www.percona.com/doc/percona-xtrabackup/2.2/

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

Кроме того, версия MySQL, начиная с 5.5 - InnoDB работает быстрее, чем MyISAM. Подумайте о замене на него всех своих таблиц.

person Tata    schedule 26.04.2015
comment
Повлияет ли изменение таблиц с MyISAM на InnoDB на какое-либо отношение? или какой-либо ущерб моей БД? Есть ли какое-то конкретное преимущество в использовании MyISAM, а не в InnoDB? - person dharanbro; 28.04.2015
comment
Если вы спросите кого-нибудь из экспертов по MySQL - все они ответят - нет. Сегодня нет никаких преимуществ в использовании MyISAM перед InnoDB. Но вам нужно проверить код, который использует ваши таблицы, и убедиться, что он не полагается на блокировки таблиц, которые выполняет MyISAM. - person Tata; 29.04.2015
comment
Самая большая проблема со стандартным mysqldump и import на самом деле не в том, что жесткий диск является узким местом, самая большая проблема в том, что когда вы делаете это, вы фактически снова вставляете все данные в таблицу, а не просто копируете структуру данных. Итак, вам нужно воссоздать структуру. Это серьезное ограничение программного обеспечения, которое усугубляется медленными дисками. MyISAM имеет реальное преимущество перед Innodb, когда дело доходит до резервного копирования: вы можете просто заблокировать и очистить таблицы и скопировать данные с помощью cp или scp, и он отлично работает (не забудьте указать mysql: mysql для файлов). - person Chris Seline; 30.05.2016
comment
@ChrisSeline - вы можете сделать то же самое с таблицами InnoDB, но когда вы это сделаете, ваша БД не будет работать. Не пытайтесь таким образом создать резервную копию 1 ТБ данных из производственной БД. - person Tata; 05.06.2016
comment
Сделать это с InnoDB намного сложнее. У меня был некоторый успех при копировании всего db с таблицами InnoDB с использованием scp, но я никогда не добивался успеха с одной таблицей. И вы по-прежнему можете создавать резервные копии производственных данных, вы просто не можете писать в таблицу, пока делаете это :). В любом случае, я уверен, что инструмент Percona существует именно поэтому, потому что это заноза в заднице! - person Chris Seline; 09.06.2016

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

Было бы намного эффективнее, если бы вы могли копировать файлы данных в формате, который MySQL уже понимает. Хороший способ сделать это - использовать innobackupex из Percona

(Открытый исходный код и распространяется как часть XtraBackup, доступного для загрузки с здесь).

Это сделает снимок таблиц MyISAM, а для таблиц InnoDB он скопирует базовые файлы, а затем воспроизведет журнал транзакций для них, чтобы гарантировать согласованное состояние. Он может делать это с живого сервера без простоев (я понятия не имею, является ли это вашим требованием?)

Я предлагаю вам прочитать документацию, но чтобы сделать резервную копию в простейшей форме, используйте:

$ innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
$ innobackupex --apply-log /path/to/BACKUP-DIR/

Если данные находятся на одном компьютере, то в innobackupex даже есть простая команда восстановления:

$ innobackupex --copy-back /path/to/BACKUP-DIR

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

Что касается скорости, наш медленный тестовый сервер, который выполняет около 600 операций ввода-вывода в секунду, может восстановить резервную копию объемом 500 ГБ примерно за 4 часа, используя этот метод.

И наконец: вы упомянули, что можно сделать для ускорения импорта. Это в основном будет зависеть от горлышка бутылки. Как правило, операции импорта связаны с вводом-выводом (вы можете проверить это, проверив наличие io-ожиданий), и способ ускорить это - за счет более высокой пропускной способности диска - либо сами диски быстрее, либо их большее количество одновременно.

person AndySavage    schedule 23.04.2015

Единственное, что ты можешь сделать, это

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS=0

И вы также можете поиграть со значениями

innodb_buffer_pool_size
innodb_additional_mem_pool_size
innodb_flush_method

в my.cnf, чтобы вы начали, но в целом вам следует взглянуть на остальные параметры innodb, чтобы узнать, что вам больше подходит.

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

person fakedrake    schedule 15.04.2015
comment
в настоящее время выполняется обычный импорт. как только это будет сделано, позволь мне попробовать это - person dharanbro; 15.04.2015
comment
установка innodb_buffe_pool_size в my.cnf не запускает сервер mysql - person dharanbro; 21.04.2015
comment
@DharanBro Это потому, что вы неправильно написали. - person user207421; 24.04.2015

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

mysql --max_allowed_packet=256M -u root -p < "database-file.sql"
person koolkoda    schedule 28.04.2015
comment
max_allowed_packet = 512M находится в конфиге, поэтому увеличение 256M фактически уменьшит его размер. - person Tata; 29.04.2015

Способ 1: отключить внешние ключи, как предложил fakedrake.

УСТАНОВИТЬ АВТОКОММИТ = 0; УСТАНОВИТЬ FOREIGN_KEY_CHECKS = 0

Способ 2: используйте BigDump, он разбивает ваш файл mysqldump, а затем импортирует его. http://www.ozerov.de/bigdump/usage/

Вопрос: Вы сказали, что загружаете? как вы импортируете свой дамп? не прямо из сервера / командной строки?

person vivex    schedule 28.04.2015

Мне приходилось сталкиваться с той же проблемой. Я нашел использование mysqldump для вывода в файл CSV (например, здесь):

mysqldump -u [username] -p -t -T/path/to/db/directory [database] --fields-enclosed-by=\" --fields-terminated-by=,

а затем импортировать эти данные с помощью запроса LOAD DATA INFILE из клиента mysql (вот так):

LOAD DATA FROM INFILE /path/to/db/directory/table.csv INTO TABLE FIELDS TERMINATED BY ',';

быть примерно на порядок быстрее, чем просто выполнение SQL-запросов, содержащих данные. Конечно, это также зависит от уже созданных (и пустых) таблиц.

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

person Vinbot    schedule 28.04.2015
comment
Одно большое предостережение при использовании параметра -T с msyqldump заключается в том, что он работает только в том случае, если mysqldump запущен на том же компьютере, что и сервер mysqld. - person erstaples; 30.05.2018

Получите больше оперативной памяти, получите более быстрый процессор, получите SSD для более быстрой записи. Сгруппируйте пластины так, чтобы они работали быстрее, чем набор отдельных пластин. Это огромный файл, и на него потребуется время.

person holtc    schedule 28.04.2015

Метод, описанный в [ответ Винбота выше] [1] с использованием LOAD DATA INFILE - это то, как я ежедневно использую около 1 ГБ для процесса анализа на моем локальном рабочем столе (у меня нет администратора баз данных или CREATE TABLErights на сервере, но у меня есть локальный mySQL).

Новая функция, представленная в mySQL 8.0.17, [Утилита импорта параллельных таблиц mySQL] [2], выводит ее на новый уровень.

Импорт таблиц CSV, который раньше занимал около 15 минут (примерно 1 ГБ), теперь занимает 5:30 на Intel Core I7-6820HQ с SATA SSD. Когда я добавил диск nVME M.2 1Tb WD Black (купленный для старого настольного компьютера, но оказалось несовместимым) и переместил установку mySQL на этот диск, время упало до 4 минут 15 секунд.

Я определяю большинство своих индексов в определениях таблиц до запуска утилиты. Без индексации загрузка выполняется еще быстрее, но индексация после загрузки занимает больше общего времени. Это имеет смысл, поскольку многоядерная функция параллельного загрузчика распространяется на создание индексов.

Я также ALTER INSTANCE DISABLE INNODB REDO_LOG (представил 8.0.21) в служебном скрипте параллельного загрузчика. Обратите внимание на предупреждение, чтобы не оставлять это отключенным после завершения массовой загрузки. Я не включил его повторно и в итоге получил поврежденный экземпляр (не только таблицы, но и весь экземпляр). Я всегда отключаю двойную буферизацию записи.

Монитор ЦП показывает, что утилита полностью использует все 8 ядер.

После завершения работы с параллельным загрузчиком он возвращается к однопоточному mySQL (для моего линейного набора задач анализа, а не для многопользовательского режима). Новый nVME сокращает время примерно на 10%. Утилита экономит мне несколько минут каждый день.

Утилита позволяет управлять размерами буфера и количеством потоков. Я подбираю количество физических ядер в моем процессоре (8), и это кажется оптимальным. (Первоначально я пришел в эту ветку в поисках советов по оптимизации настройки параллельного загрузчика). [1]: https://stackoverflow.com/a/29922299/5839677 [2]: https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-utilities-parallel-table.html

person wistlo    schedule 08.09.2020

Я не уверен, что это вариант для вас, но лучший способ сделать это - это то, что уже сказали Tata и AndySavage: сделать снимок файлов данных с рабочего сервера, а затем установить их на свой локальный компьютер с помощью Percona. innobackupex. Он будет создавать резервные копии таблиц InnoDb согласованным образом и выполнять блокировку записи для таблиц MyISAM.

Подготовьте полную резервную копию на производственной машине:

http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/preparing_a_backup_ibk.html

Скопируйте (или по конвейеру через SSH при создании резервной копии - подробнее здесь) резервные копии файлов на локальный компьютер и их восстановление:

Восстановите резервную копию:

http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/restoring_a_backup_ibk.html

Вы можете найти полную документацию по innobackupex здесь: http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/innobackupex_script.html.

Время восстановления будет НАМНОГО быстрее, чем чтение дампа SQL.

person Diego    schedule 28.04.2015