ความเร็วในการโหลดข้อมูลช้าจาก mysqldump


21

ฉันมีฐานข้อมูล MySQL ขนาดปานกลางที่มีประมาณ 30 ตารางซึ่งบางส่วนเป็น 10 ล้านบันทึกบาง 100 ล้าน mysqldumpของตารางทั้งหมด (เป็นไฟล์ที่แยกต่างหาก) เป็นธรรมอย่างรวดเร็วใช้เวลาอาจจะ 20 นาที มันสร้างข้อมูลประมาณ 15GB ไฟล์ที่ทิ้งที่ใหญ่ที่สุดอยู่ในช่วง 2GB

เมื่อฉันโหลดข้อมูลลงใน MySQL บนอีกกล่องหนึ่งเครื่องหกคอร์ 8GB ซึ่งใช้เวลานาน ได้อย่างง่ายดาย 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 = 2my.cnf ของคุณชั่วคราวขณะที่การนำเข้ากำลังทำงาน คุณสามารถใส่กลับไปที่ 1 หากคุณต้องการกรด

ให้มันลอง..


คำใบ้ของคุณinnodb_flush_log_at_trx_commit = 2ช่วยชีวิตฉันไว้ การนำเข้าดัมพ์ 600 MB (เป็นธุรกรรมขนาดใหญ่ครั้งเดียว) จะต้องใช้เวลา 6 ชั่วโมง แต่ด้วยการตั้งค่าชั่วคราวนี้เสร็จภายใน 30 นาที!
Daniel Marschall

1
สิ่งที่คุณต้องการให้คุณรู้ก่อนพยายามโหลดฐานข้อมูล 80gig จากการถ่ายโอนข้อมูล 4 วันหลังจากกดปุ่ม 'Enter' ... :)
Dmitri DB

7

นอกเหนือจากคำตอบของ Abdulฉันต้องการเน้นความสำคัญของ--disable-keysตัวเลือกซึ่งจะปิดแป้นจนกว่าจะมีการโหลดข้อมูลทั้งหมดสำหรับตาราง ตัวเลือกนี้เปิดใช้งานเป็นส่วนหนึ่งของการ--optสลับซึ่งเปิดใช้งานโดยค่าเริ่มต้น แต่คิดว่ามันเป็นสิ่งสำคัญที่จะชี้ให้เห็น

หากคุณไม่ข้ามคีย์ระหว่างส่วนแทรกแต่ละแถวที่แทรกจะสร้างดัชนีใหม่ กระบวนการที่ช้ามาก


- ปิดการใช้งานคีย์เป็นส่วนหนึ่งของ 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
อีธานอัลเลน

7

เมื่อไม่นานมานี้ฉันได้ติดต่อกับสิ่งนี้มาก คุณสามารถปรับปรุงประสิทธิภาพการนำเข้าได้อย่างแน่นอนด้วยการนำเข้าแบบขนาน การชะลอตัวส่วนใหญ่เป็นไปตาม I / O แต่คุณยังคงได้รับการปรับปรุง 40% โดยการเทลงในตารางแล้วนำเข้าพวกเขาบอกว่า 4 ครั้ง

คุณสามารถทำได้ด้วย xargs เช่นนี้

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

มีไฟล์ gzipped ก่อนที่จะผลักพวกเขาไปยัง mysql ไม่ได้ช้าลงเพราะส่วนใหญ่ I / O ที่ลดลง ตารางของฉันถูกบีบอัดได้สูงสุดประมาณ 10: 1 ดังนั้นจึงช่วยประหยัดพื้นที่ดิสก์ได้มาก

ฉันพบว่าบนเครื่อง 4 แกนการใช้ 4 กระบวนการนั้นดีที่สุดแม้ว่าจะดีกว่าการใช้ 3 เล็กน้อยหากคุณมี SSD หรือ RAID ที่รวดเร็วคุณก็น่าจะขยายได้ดีขึ้น

สิ่งอื่นที่ควรทราบ ถ้าคุณมีไดรฟ์ 4k ภาคแน่ใจว่าคุณมีและkey_cache_block_size=4096myisam_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

(สามครั้งสุดท้ายที่ฉันไม่ได้ทดสอบอย่างกว้างขวาง - ฉันคิดว่าฉันพบว่าพวกเขาเป็นคำแนะนำเกี่ยวกับ internets.) โปรดทราบว่าinnodb_flush_log_at_commit=0อาจส่งผลให้เกิดความเสียหายกับ mysql crashing หรือกำลังจะออกไป


Greg ยินดีต้อนรับสู่เว็บไซต์และขอบคุณสำหรับคำตอบของคุณ คุณสามารถให้แหล่งที่มาบางส่วนหรือเหตุผลสำหรับคำแนะนำของคุณบน*_block_sizeและmyisam_repair_threads? นอกจากนี้ไม่แน่ใจว่าเราควรให้คำแนะนำในการปรับตัวแปรตาม 'คำแนะนำจากผู้ฝึกงาน' :)
Derek Downey

5

หากคุณส่วนใหญ่มีตาราง MyISAM คุณควรเพิ่มบัฟเฟอร์กลุ่มแทรก นี่คือสิ่งที่เอกสาร MySQL ระบุไว้ในการตั้งค่าbulk_insert_buffer_size :

MyISAM ใช้แคชที่มีลักษณะคล้ายต้นไม้เป็นพิเศษเพื่อให้แทรกจำนวนมากได้เร็วขึ้นสำหรับ INSERT ... SELECT, INSERT ... VALUES (... ), (... ), ... , ... , และโหลดข้อมูล 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 ควรใช้เวลา 3 ครั้งตราบเท่าที่ mysqldump ใช้ทำ ฉันยังยินดีเป็นอย่างยิ่งว่าการโหลด InnoDB mysqldump ควรใช้เวลา 4 ครั้งตราบเท่าที่ mysqldump ใช้ทำ

หากคุณมีอัตราส่วนเกินกว่า 4: 1 สำหรับการโหลด mysqldump คุณมีปัญหาอย่างใดอย่างหนึ่งจากสองข้อ:

  • ดัชนีมากเกินไป
  • ดัชนีใหญ่เกินไปเนื่องจากคอลัมน์ใหญ่

คุณสามารถวัดขนาดข้อมูลของคุณโดยใช้เครื่องมือจัดเก็บข้อมูลด้วยสิ่งนี้:

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. เพิ่ม mysql; rmdir mysql
  11. ย้าย mysql2 ไปยัง mysql
  12. เริ่ม mysqld มีความสุข

สำหรับฉันการถ่ายโอนข้อมูลของ ~ 10G (/ var / lib / mysql บริโภค ~ 20G) สามารถนำเข้าในเวลาประมาณ 35 นาที (mydumper / myloader), 45 นาที (mysqldump --tab / mysqlimport), 50 นาที (mysqldump / mysql) บน Xeon 3.2x6-core

หากคุณมี RAM ไม่เพียงพอในเครื่องเดียว แต่มีคอมพิวเตอร์หลายเครื่องติดกันด้วยเครือข่ายที่รวดเร็วมันน่าสนใจที่จะดูว่า RAM ของพวกเขาสามารถเข้าร่วมกับ nbd (อุปกรณ์บล็อกเครือข่าย) ได้หรือไม่ หรือด้วย innodb_file_per_table คุณอาจทำซ้ำขั้นตอนข้างต้นสำหรับแต่ละตาราง


ฉันพยายามจัดเก็บ mysql datadir ใน RAM เพื่อเปรียบเทียบกับ SSD (SSDSC2BB48 สำหรับผู้ที่สนใจ) สำหรับฐานข้อมูล 2 GB ผลลัพธ์เป็นข้อมูลประจำตัวทั้งสองใช้เวลา 207-209 วินาที เมื่อพิจารณาถึงความจริงที่ว่าคุณต้องเริ่ม / หยุด mysql และคัดลอกไดเรกทอรีโดยใช้ RAM disk แทน SSD นั้นช้ากว่ามากในกรณีของฉัน
Shocker

ถ้าคุณใช้เวลาประมาณ 3-4 นาทีฉันเดาว่าคุณมีฐานข้อมูลขนาดเล็กกว่าหัวข้อนี้มาก เป็นที่น่าสนใจที่จะได้ยินเกี่ยวกับประสบการณ์ของคุณกับฐานข้อมูลขนาดใหญ่ที่คล้ายคลึงกันมากกว่าที่กล่าวไว้ในหัวข้อนี้
egmont
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.