mysqldump에서 느린 데이터로드 속도


21

약 30 개의 테이블이있는 적당한 크기의 MySQL 데이터베이스가 있으며 그중 일부는 천만 개의 레코드, 약 1 억 개의 레코드입니다. mysqldump(별도의 파일로) 모든 테이블은 상당히 빠르고 아마 20 분 소요됩니다. 약 15GB의 데이터를 생성합니다. 가장 큰 덤프 파일은 2GB 범위에 있습니다.

6 코어 8GB 시스템 인 다른 상자에서 MySQL로 데이터를로드 할 때 시간이 오래 걸립니다. 12 시간 이상의 시계.

파일을로드하기 위해 mysql 클라이언트를 실행 중입니다.

mysql database < footable.sql

mysqldump에서 직접 파일로 직접

mysqldump database foo > footable.sql

분명히 나는 ​​뭔가 잘못하고 있습니다. 적당한 시간에 끝내려면 어디서부터 시작해야합니까?

덤프 또는로드에서 스위치를 사용하지 않습니다.


덤프를로드하는 동안 바이너리 로깅을 비활성화 할 수도 있습니다.
Cédric PEINTRE

답변:


22

덤프를 생성하고 복원 할 때 도움이 될 수있는 사항을 고려하십시오.

  1. Extended inserts덤프에 사용하십시오 .
  2. 보다 빠른 --tab형식을 사용하여 덤프 할 수 있습니다 .mysqlimportmysql < dumpfile
  3. 각 테이블 당 하나씩 여러 스레드를 가져옵니다.
  4. 가능하면 다른 데이터베이스 엔진을 사용하십시오. innodb와 같이 트랜잭션이 많은 엔진으로 가져 오는 것은 상당히 느립니다. MyISAM과 같은 비 트랜잭션 엔진에 삽입하는 것이 훨씬 빠릅니다.
  5. 외래 키 검사를 끄고 자동 커밋을 켭니다.
  6. innodb로 가져 오는 경우 가장 효과적인 방법 innodb_flush_log_at_trx_commit = 2은 가져 오기가 실행되는 동안 my.cnf를 임시 로 넣는 것 입니다. ACID가 필요한 경우 1로 되돌릴 수 있습니다

시도 해봐..


당신의 힌트는 innodb_flush_log_at_trx_commit = 2내 하루 를 저장했습니다. 600MB 덤프 (단일 큰 트랜잭션)를 가져 오는 데 6 시간이 필요했지만이 임시 설정으로 30 분 안에 완료되었습니다!
Daniel Marschall

1
'enter'를 치고 4 일 후 덤프에서 80gig 데이터베이스를로드하기 전에 알고 싶은 사항 : :)
Dmitri DB

7

Abdul의 답변 외에도 --disable-keys옵션 의 중요성을 강조하고 싶습니다.이 옵션은 테이블에 대한 모든 데이터가로드 될 때까지 키를 끕니다. 이 옵션은 --opt토글의 일부로 활성화되며 기본적으로 활성화되어 있지만 지적하는 것이 중요하다고 생각했습니다.

삽입하는 동안 키를 건너 뛰지 않으면 삽입 된 각 행이 색인을 다시 작성합니다. 매우 느린 과정.


--disable-keys는 mysqldump의 일부입니까? 또는 새로 고침?
Pat Farrell

덤프 파일에 추가됩니다
Derek Downey

--opt기본적으로 설정되어 있습니다
jberryman

1
This option is effective only for nonunique indexes of MyISAM tables. It has no effect for other tables
Ethan Allen

7

나는 이것을 최근에 많이 다루어왔다. 가져 오기를 병렬로 수행하여 가져 오기 성능을 확실히 향상시킬 수 있습니다. 대부분의 속도 저하는 I / O 기반이지만 테이블에 덤프 한 다음 한 번에 4 개씩 가져 오면 여전히 40 % 향상 될 수 있습니다.

다음과 같이 xargs로이를 수행 할 수 있습니다.

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

파일을 mysql에 푸시하기 전에 파일을 압축해도 I / O가 낮아져서 속도가 느려지지 않습니다. 내 테이블은 약 10 : 1까지 압축되어 디스크 공간을 많이 절약합니다.

4 코어 시스템에서 4 프로세스를 사용하는 것이 최적이지만 3을 사용하는 것보다 조금 나아진 것으로 나타났습니다. SSD 또는 빠른 RAID가 있으면 확장 성이 더 좋습니다.

주목할 다른 것들. 당신이 4K 섹터 드라이브가있는 경우, 확인, 당신은 key_cache_block_size=4096하고 myisam_block_size=4K.

MyISAM 테이블을 사용하는 myisam_repair_threads = 2경우 이상을 설정하십시오 . 이렇게하면 추가 코어가 인덱스를 다시 작성하는 데 도움이됩니다.

전혀 교환하지 않아야합니다. 그렇다면의 크기를 줄이십시오 innodb_buffer_pool_size.

나는이 옵션들에 의해 innnodb로 속도를 올렸다고 생각합니다.

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(마지막으로 테스트하지 않은 마지막 3 개-인터넷에서 제안으로 찾았습니다.) innodb_flush_log_at_commit=0mysql이 충돌하거나 전원이 꺼지면 손상 될 수 있습니다.


Greg, 사이트에 오신 것을 환영합니다. 답변 해 주셔서 감사합니다. 당신의 제안에 대한 몇 가지 소스 나 추론을 제공 할 수 *_block_sizemyisam_repair_threads? 또한, 확실히 우리는 :) '는 internets의 제안'에 따라 조정 변수에 대한 조언을 제공해야하지
데릭 다우니

5

주로 MyISAM 테이블이있는 경우 대량 삽입 버퍼를 늘려야합니다 . 다음은 bulk_insert_buffer_size 설정에 대한 MySQL 설명서의 내용입니다 .

MyISAM은 특수 트리와 같은 캐시를 사용하여 비어 있지 않은 데이터를 추가 할 때 INSERT ... SELECT, INSERT ... VALUES (...), (...), ... 및 LOAD DATA INFILE에 대한 대량 삽입을 더 빠르게 만듭니다. 테이블. 이 변수는 캐시 트리의 크기를 스레드 당 바이트 수로 제한합니다. 0으로 설정하면이 최적화가 비활성화됩니다. 기본값은 8MB입니다.

당신이해야 할 두 가지가 있습니다

1) /etc/my.cnf에 추가하십시오

[mysqld]
bulk_insert_buffer_size=512M

2) 글로벌 가치 설정

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

bulk_insert_buffer_size를 전체적으로 설정할 권한이없는 경우 다음을 수행하십시오.

service mysql restart

물론 이것은 InnoDB를위한 것이 아닙니다.

다른 각도에서 테이블이 InnoDB이든 MyISAM이든 인덱스가 테이블보다 크면 인덱스가 너무 많을 수 있습니다. 나는 보통 MyISAM mysqldump의 재로드가 mysqldump가 만드는 데 3 배가 걸린다는 것을 손님에게 이야기한다. 또한 InnoDB mysqldump의 재로드는 mysqldump가 만드는 데 4 배가 걸린다는 것을 손님에게 이야기합니다.

mysqldump를 다시로드 할 때 4 : 1 비율을 초과하는 경우 다음 두 가지 문제 중 하나가 발생합니다.

  • 너무 많은 색인
  • 큰 열로 인해 너무 큰 인덱스

다음을 사용하여 스토리지 엔진별로 데이터 크기를 측정 할 수 있습니다.

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

인덱스가 데이터보다 크거나 같은지 확인하십시오

다음과 같이 이진 로깅을 비활성화하는 것을 고려할 수도 있습니다.

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

스크립트를 다시로드하기 전에


하루를 몇 번이나 저장했는지 모르겠지만 확실히 많은 시간을
Dmitri DB

2

파일 시스템을 완전히 우회하고 mysqldump의 출력을 MySQL 프로세스에 직접 파이프하면 성능이 크게 향상됩니다. 궁극적으로 사용하는 디스크 드라이브의 유형에 따라 달라 지지만이 이유로 데이터베이스 크기에 관계없이 덤프 파일은 더 이상 사용하지 않습니다.

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy

1

내 경험에 따르면 하드 드라이브는 병목 현상입니다. 회전하는 디스크는 잊어 버리십시오. SSD가 더 좋지만, 전체 데이터베이스를 잠시 동안 보유 할만큼 충분한 경우 RAM에서이를 수행하는 것이 가장 좋습니다. 대충:

  1. mysqld를 중지
  2. / var / lib / mysql의 기존 내용을 옮기십시오
  3. 빈 / var / lib / mysql 디렉토리를 만듭니다.
  4. mount -t tmpfs -o size = 32g tmpfs / var / lib / mysql (크기 조정)
  5. 빈 db (예 : mysql_install_db 또는 이전 내용 복원)를 만듭니다.
  6. mysqld를 시작
  7. 수입
  8. mysqld를 중지
  9. / var / lib / mysql을 mysql2로 복사
  10. umount mysql; rmdir mysql
  11. mysql2를 mysql로 ​​이동
  12. mysqld를 시작하고 행복해

저에게 ~ 10G (/ var / lib / mysql 소비 ~ 20G) 덤프는 약 35 분 (mydumper / myloader), 45 분 (mysqldump --tab / mysqlimport), 50 분 (mysqldump / mysql)으로 가져올 수 있습니다. , 2x6 코어 3.2GHz Xeon에서.

단일 컴퓨터에 충분한 RAM이 없지만 빠른 네트워크로 서로 옆에 여러 대의 컴퓨터가있는 경우 RAM이 nbd (네트워크 블록 장치)와 연결될 수 있는지 확인하는 것이 흥미로울 것입니다. 또는 innodb_file_per_table을 사용하면 각 테이블에 대해 위의 프로세스를 반복 할 수 있습니다.


호기심 때문에 2GB 데이터베이스의 SSD (관심있는 사람들을 위해 SSDSC2BB48)와 비교하기 위해 mysql datadir을 RAM에 저장하려고했습니다. 결과는 동일했으며, 둘 다 207-209 초가 걸렸습니다. 훨씬 느린 내 경우에 당신은 또한 대신 SSD의 RAM 디스크를 사용, 시작 / 정지 mysql을을 가지고 있으며 디렉토리를 복사하는 것이 사실이었다 고려
쇼커

~ 3-4 분이 걸린다면이 주제에 대한 것보다 훨씬 작은 데이터베이스를 가지고 있다고 생각합니다. 이 주제에서 언급 한 데이터베이스와 비슷한 규모의 데이터베이스에 대한 경험을 들어 보면 흥미로울 것입니다.
egmont
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.