MySQL 테이블에 약 4 천만 개의 행이 있으며이 테이블을 동일한 데이터베이스의 다른 테이블에 복사하려고합니다. 가장 효율적인 방법은 무엇입니까? 시간이 얼마나 걸립니까 (약)?
MySQL 테이블에 약 4 천만 개의 행이 있으며이 테이블을 동일한 데이터베이스의 다른 테이블에 복사하려고합니다. 가장 효율적인 방법은 무엇입니까? 시간이 얼마나 걸립니까 (약)?
답변:
당신이 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 천만 행의 단일 거래를 할 것이다
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
이 방법은 테이블을 삭제하지 않습니다. 그것은 단순히 INSERT를 생성합니다
DB 서버의 구성, 테이블 구조, 인덱스 레이아웃 및 이와 유사한 것을 모르기 때문에 시간을 예상 할 수 없습니다.
MyISAM *과 달리 InnoDB 테이블은 데이터 딕셔너리의 일부 (및 병합 버퍼와 같이 테이블이 의존하는 다른 구조)가 메모리 (서버가 실행중인 경우)에 있고 큰 파일 불리는 일명하는 일반 / 메인 테이블, ibdata1
.
Percona Server> = 5.1 또는 MySQL> = 5.6을 사용하는 경우, 이동 가능한 테이블 스페이스가 지원되므로 파일 시스템에서 직접 테이블을 내보내고 가져올 수 있습니다. 다음은 MySQL 과 Percona를 위한 방법입니다 . 두 경우 모두, innodb_file_per_table
옵션을 사용 하여 테이블을 작성 해야하고 DISCARD TABLESPACE/IMPORT TABLESPACE
Percona Xtrabakup 의 사용법 및 / 또는 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
한 번 행 당. 이 방법을 사용하는 경우 내구성 옵션을 일시적으로 비활성화하고 큰 버퍼 풀과 트랜잭션 로그가 있는지 확인하십시오. 이러한 상황에서는 가져 오기 시간이 단축 될 수 있지만 메모리에 완전히 맞지 않을 수 있으므로 많은 시간이 필요합니다. 또한 단일 트랜잭션에서 4 천만 행을 가져 오려고하면 문제가 발생할 수 있습니다.
이 두 번째 경우의 실제 권장 사항 은 pt-archiver 와 같은 것을 사용 하는 것입니다. 방금 언급 한 것과 비슷한 작업을 수행하지만 트랜잭션 오버 헤드를 피하면서 "청크"로 수행됩니다 더 빠르지는 않지만 실패의 경우 전체 테이블을 롤백하지 않고 영원히 가져갑니다.) 언급 한 데이터 크기의 경우 이것이 가장 좋은 방법 일 것입니다.
마지막 옵션은 SELECT INTO OUTFILE / mysqldump 및 LOAD DATA / mysqlimport의 조합 으로 CSV (또는 TSV) 형식을 사용하여 내보내고 가져 오는 것입니다. 이것은 sql을 사용하여 더 큰 잠금을 생성했기 때문에 특정 이전 버전의 mysql에서 동시성이 필요한 경우 매우 일반적인 옵션이었습니다. mysqldump / import는 직렬화 된 방식으로 만 작동하므로 병렬화하는 옵션을 조사하여 큰 테이블에 매우 유용합니다.
어쨌든 여러 쿼리를 실행하는 경우 (개별적으로 실행, 구문 분석 및 최적화해야 함) 가장 중요한 병목 현상이 발생하므로 여러 SQL 문장을 피하십시오.
* MyISAM 구조는 빠른 방법으로 복사 할 수 없지만을 사용하여 임시로 디스크에 동기화하는 것은 매우 쉽습니다 FTWRL
.