У меня около 40 миллионов строк в таблице MySQL, и я хочу скопировать эту таблицу в другую таблицу в той же базе данных. Каков наиболее эффективный способ сделать это? Сколько времени это займет (прибл.)?
У меня около 40 миллионов строк в таблице MySQL, и я хочу скопировать эту таблицу в другую таблицу в той же базе данных. Каков наиболее эффективный способ сделать это? Сколько времени это займет (прибл.)?
Ответы:
Предположим, у вас есть, mydb.mytb
и вы хотите создатьmydb.mytbcopy
У меня есть пять (5) подходов к созданию этой копии
В mysql
клиенте запустите следующее
USE mydb
CREATE TABLE mytbcopy LIKE mytb;
INSERT INTO mytbcopy SELECT * FROM mytb;
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb | mysql ${MYSQL_CONN} -Dtest
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dtest < ${DUMPFILE}
rm -f ${DUMPFILE}
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dmydb < ${DUMPFILE}
rm -f ${DUMPFILE}
Если вы хотите скопировать mydb.mytb
в уже существующую таблицу mydb.mytbcopy
, и две таблицы имеют идентичные структуры:
INSERT INTO mytbcopy SELECT * FROM mytb;
Подобно #APPROACH 1 , #APPROACH 6 будет иметь одну транзакцию из 40 миллионов строк
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} -t mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
Этот подход не опускает стол. Он просто генерирует ВСТАВКИ
Я не могу дать вам оценку времени, так как я не знаю состав сервера БД, структуру таблицы, структуру индекса и тому подобное.
Таблицы InnoDB, в отличие от MyISAM *, нельзя «просто скопировать», поскольку часть их словаря данных (и, возможно, других структур, от которых зависит таблица, например, буфер слияния) расположены в памяти (если сервер работает) и в общее / основное табличное пространство, называемое тем большим файлом ibdata1
.
Если вы используете Percona Server> = 5.1 или MySQL> = 5.6, есть поддержка переносимых табличных пространств, которая позволяет вам экспортировать и импортировать таблицы непосредственно из файловой системы. Здесь это метод для MySQL и для Percona . В обоих случаях требуется, чтобы вы создали таблицу с этой innodb_file_per_table
опцией и DISCARD TABLESPACE/IMPORT TABLESPACE
включали использование и / или Percona Xtrabakup (если вы хотите, чтобы экспорт осуществлялся онлайн). Обратите внимание, что Percona Server или Xtrabakup недоступны для Windows.
В общем случае этот метод будет таким же быстрым, как копирование файла с помощью команд файловой системы (cp, rsync).
Хотя могут быть некоторые случаи, когда это может работать в MySQL <5.6 (хакерским способом) для восстановления, это не будет работать для копии таблицы. В этих случаях одним из способов сделать это является использование SQL :
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
Это будет так же быстро, как InnoDB, Handler_read_rnd_next
и Handler_write
один раз за строку. Если вы используете этот метод, убедитесь, что вы отключили, хотя бы временно, параметры долговечности, и у вас есть большой пул буферов и журнал транзакций. При таких обстоятельствах это может сократить время импорта, но определенно не уместится в память полностью, поэтому ожидайте много времени. Кроме того, вы пытаетесь импортировать 40M строк в одной транзакции, что может привести к проблемам.
Моя фактическая рекомендация в этом втором случае - использовать что-то вроде pt-archiver , поскольку он будет выполнять операцию, аналогичную той, которую я только что упомянул, но это будет выполняться «кусками», избегая накладных расходов на транзакции (это может не будет быстрее, но в случае сбоя он не будет пытаться откатить всю таблицу, занимая вечность). Для размеров данных, которые вы упоминаете, это, вероятно, лучший путь.
Последний вариант - экспорт и импорт в формате CSV (или TSV) с комбинацией SELECT INTO OUTFILE / mysqldump и LOAD DATA / mysqlimport. Это был очень распространенный вариант, если вам требовался параллелизм в некоторых старых версиях mysql, так как использование sql создавало большие блокировки (больше не верно, если все сделано правильно). Поскольку mysqldump / import работает только в последовательном порядке, я бы порекомендовал вам изучить варианты его распараллеливания, что очень полезно для больших таблиц.
В любом случае, старайтесь избегать множественных предложений SQL, так как это будет вашим самым важным узким местом, если вы выполняете много разных запросов (которые должны выполняться, анализироваться и оптимизироваться индивидуально).
* Структуры MyISAM не могут быть скопированы горячим способом, но их очень легко временно синхронизировать с диском FTWRL
.
Переместить данные из одной таблицы в другую в схеме
create table your_table_name select * from old_schema_table;