Скопіюйте з однієї таблиці MySQL в іншу таблицю MySQL тієї ж бази даних


15

У таблиці MySQL у мене близько 40 мільйонів рядків, і я хочу скопіювати цю таблицю в іншу таблицю тієї ж бази даних. Який найефективніший спосіб зробити це? Скільки часу це займе (приблизно)?


Що таке двигун вашого столу?
Абдул Манаф

InnoDB Engine ..
Devashish Dixit

Відповіді:


23

Припустимо, у вас є mydb.mytbі ви хочете створитиmydb.mytbcopy

У мене є п'ять (5) підходів до виконання цієї копії

ПІДХІД №1

У mysqlклієнті виконайте наступне

USE mydb
CREATE TABLE mytbcopy LIKE mytb;
INSERT INTO mytbcopy SELECT * FROM mytb;

ПІДХІД №2

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"

ПІДХІД №3

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"

ПІДХІД №4

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

ПІДХІД №5

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}

АНАЛІЗ

  • ПІДХІД №1 є найпростішим з точки зору кроків, але вимагає введення 40 мільйонів рядків в одну транзакцію. Це буде найбільше оподаткування двигуна зберігання InnoDB.
  • Для інших підходів mysqldump надішле 40 мільйонів рядків в патронах тисячі рядків
    • ПІДХІД №2 та ПІДХІД №3 перейдуть на таблицю в тестову базу даних. Після створення таблиці в тестовій базі даних вона згодом перейменовується і переміщується в початкову базу даних
    • ПІДХІД №4 та ПІДХОД №5 перейменують таблицю за допомогою sed проти потоку, що надходить з mysqldump, як це повторює команди INSERT
    • ПІДХІД №2 та ПІДХІД №4 використовують труби замість вихідного файлу
    • ПІДХІД №3 та ПІДПРИЄМКА №5 використовують вивідний файл для подальшого перезавантаження

Якщо ви хочете скопіювати mydb.mytbу вже існуючу таблицю mydb.mytbcopy, а дві таблиці мають однакові структури:

ПІДХІД №6

INSERT INTO mytbcopy SELECT * FROM mytb;

Як і #APPROACH 1 , #APPROACH 6 матиме одну транзакцію в 40 мільйонів рядків

ПІДХІД №7

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

Цей підхід не опускає таблицю. Він просто генерує ВСТАВКИ

ЕПІЛОГ

Я не можу дати тобі оцінку часу, оскільки не знаю склад сервера БД, структуру таблиць, макет індексу та подібні речі.

СПРОБУВАТИ !!!


0

Таблиці 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-архіватора , оскільки воно буде виконувати операцію, подібну до тієї, про яку я щойно згадував, але це буде виконуватися "шматками", уникаючи транзакційних накладних витрат (можливо, не швидше, але у випадку невдачі, він не намагатиметься відкатати всю таблицю, займаючи назавжди). Для розмірів даних, які ви згадуєте, це, мабуть, найкращий шлях.

Остаточним варіантом буде експорт та імпорт у форматі CSV (або TSV) з комбінацією SELECT INTO OUTFILE / mysqldump та LOAD DATA / mysqlimport. Це був дуже поширений варіант, якщо вам потрібна паралельність у певних старих версіях mysql, як використання sql, створених більшими блокуваннями (більше не відповідає дійсності, якщо виконано правильно). Оскільки mysqldump / import працює лише серіалізованим способом, я рекомендую вам дослідити варіанти паралелізації, що дуже корисно для великих таблиць.

У будь-якому випадку намагайтеся уникати декількох пропозицій SQL, оскільки це буде вашим найважливішим місцем, якщо ви виконуєте безліч різних запитів (які потрібно виконувати, аналізувати та оптимізувати окремо).


* Структури MyISAM неможливо скопіювати гарячим способом, але дуже легко їх тимчасово синхронізувати на диск FTWRL.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.