MySQL มีวิธีนำเข้า sql dump ขนาดใหญ่ (32 GB) เร็วขึ้นไหม?


67

ฉันมีการถ่ายโอนข้อมูล SQL ขนาดใหญ่ 32 GB ที่ฉันต้องนำเข้าสู่ MySQL ฉันไม่ได้นำเข้าการถ่ายโอนข้อมูล SQL ขนาดใหญ่เช่นนี้มาก่อน ฉันทำตามปกติ:

mysql -uroot dbname < dbname.sql

ใช้เวลานานเกินไป มีโต๊ะที่มีแถวประมาณ 300 ล้านแถวและได้รับถึง 1.5 ล้านในเวลาประมาณ 3 ชั่วโมง ดังนั้นดูเหมือนว่าสิ่งทั้งหมดจะใช้เวลา 600 ชั่วโมง (นั่นคือ 24 วัน) และทำไม่ได้ ดังนั้นคำถามของฉันคือมีวิธีที่เร็วกว่าในการทำเช่นนี้?

ข้อมูลเพิ่มเติม / ผลการวิจัย

  1. ตารางเป็น InnoDB ทั้งหมดและไม่มีการกำหนดคีย์ต่างประเทศ อย่างไรก็ตามมีดัชนีจำนวนมาก
  2. ฉันไม่สามารถเข้าถึงเซิร์ฟเวอร์เดิมและฐานข้อมูลดังนั้นฉันจึงไม่สามารถทำการสำรองข้อมูลใหม่หรือทำสำเนา "ร้อน" เป็นต้น
  3. การตั้งค่าinnodb_flush_log_at_trx_commit = 2ตามที่แนะนำที่นี่ดูเหมือนว่าจะไม่มีการปรับปรุง (มองเห็นได้ชัดเจน / อธิบาย)
  4. สถิติเซิร์ฟเวอร์ในระหว่างการนำเข้า (จาก MySQL Workbench): https://imgflip.com/gif/ed0c8
  5. รุ่น MySQL คือ 5.6.20 ชุมชน
  6. innodb_buffer_pool_size = 16M และ innodb_log_buffer_size = 8M ฉันจำเป็นต้องเพิ่มสิ่งเหล่านี้หรือไม่?

คุณสามารถเพิ่มส่วนประกอบได้เร็วขึ้นไปยังเซิร์ฟเวอร์นั่นคือพื้นที่เก็บข้อมูล RAM และ SSD มากกว่านี้หรือไม่?

@Bert เซิร์ฟเวอร์มี RAM 8 GB ซึ่งส่วนใหญ่ไม่ได้ใช้งาน ไม่สามารถเพิ่มที่เก็บข้อมูลได้อีก มันจะช่วยได้อย่างไร จริงๆแล้วมันเป็นงานเขียนที่ช้ามาก?

คอขวดคืออะไร CPU Core ถูกตรึงไว้หรือไม่
Chris S

@ChrisS ไม่การใช้งาน CPU คือ 3 ถึง 4% ฉันไม่แน่ใจว่าสิ่งที่เป็นคอขวด ฉันคิดว่ามันเป็นดัชนี ใครจะค้นหา / ยืนยันคอขวดได้บ้าง

1
หากคุณมี sql คุณสามารถแก้ไขคำสั่งสร้างดัชนีและดูว่ามันเร็วขึ้นไหม? เมื่อคุณนำเข้าข้อมูลแล้วคุณจะต้องสร้างใหม่อีกครั้ง

คำตอบ:


84

Vadim Tkachenko จาก Percona เป็นผู้แทนภาพ InnoDB

สถาปัตยกรรม InnoDB

คุณต้องเปลี่ยนสิ่งต่อไปนี้อย่างแน่นอน

innodb_buffer_pool_size = 4G
innodb_log_buffer_size = 256M
innodb_log_file_size = 1G
innodb_write_io_threads = 16
innodb_flush_log_at_trx_commit = 0

ทำไมการตั้งค่าเหล่านี้?

  • innodb_buffer_pool_sizeจะแคชอ่านข้อมูลบ่อยๆ
  • innodb_log_buffer_size : บัฟเฟอร์ที่ใหญ่ขึ้นลดการเขียน I / O ไปยังบันทึกการทำธุรกรรม
  • innodb_log_file_size : ไฟล์บันทึกขนาดใหญ่ช่วยลดจุดตรวจและเขียน I / O
  • innodb_write_io_threads : การดำเนินการเขียนข้อมูลไปยัง.ibdไฟล์ ตามเอกสารประกอบของ MySQL บนConfiguring the Number of Background InnoDB I/O Threadsแต่ละเธรดสามารถจัดการคำขอ I / O ที่ค้างอยู่ได้มากถึง 256 รายการ ค่าเริ่มต้นสำหรับ MySQL คือ 4, 8 สำหรับเซิร์ฟเวอร์ Percona ค่าสูงสุดคือ 64
  • innodb_flush_log_at_trx_commit
    • ในกรณีที่เกิดความผิดพลาดทั้ง 0 และ 2 อาจสูญเสียข้อมูลครั้งที่สอง
    • ข้อดีคือทั้ง 0 และ 2 เพิ่มประสิทธิภาพการเขียน
    • ฉันเลือก 0 มากกว่า 2 เพราะ 0 ล้างข้อมูล InnoDB Log Buffer ไปที่ Transaction Logs (ib_logfile0, ib_logfile1) หนึ่งครั้งต่อวินาทีโดยมีหรือไม่มีการคอมมิต การตั้งค่า 2 จะทำการล้าง InnoDB Log Buffer เฉพาะเมื่อส่งข้อมูลเท่านั้น มีประโยชน์อื่น ๆ ในการตั้ง 0 เอ่ยถึง @jynus อดีตอาจารย์ผู้สอนมี

รีสตาร์ท mysql เช่นนี้

service mysql restart --innodb-doublewrite=0

สิ่งนี้ปิดใช้งาน InnoDB Double Write Buffer

นำเข้าข้อมูลของคุณ เมื่อเสร็จแล้วให้เริ่ม mysql ใหม่ตามปกติ

service mysql restart

สิ่งนี้จะเปิดใช้งาน InnoDB Double Write Buffer อีกครั้ง

ให้มันลอง !!!

SIDE หมายเหตุ: คุณควรอัพเกรด 5.6.21 สำหรับแพทช์ด้านความปลอดภัยล่าสุด


1
ฉันทำสคริปต์ลินุกซ์ทุบตีมันลดลงค่าบางอย่างในการทำงานภายในจรจัดที่มีหน่วยความจำต่ำgist.github.com/OZZlE/57d550c3cc1c1ff17481e465e4f6d674
ชีวิตคู่

9

คุณต้องการกู้คืนฐานข้อมูลทั้งหมดหรือไม่ ถ้าคุณทำไม่ได้ 2c ของฉัน:

คุณสามารถแยกตารางที่เฉพาะเจาะจงเพื่อทำการคืนค่าของคุณใน "ชิ้น" บางสิ่งเช่นนี้

zcat your-dump.gz.sql | sed -n -e '/DROP TABLE.*`TABLE_NAME`/,/UNLOCK TABLES/p' > table_name-dump.sql

ฉันทำครั้งเดียวและใช้เวลา 10 นาทีในการแยกตารางที่ฉันต้องการ - การกู้คืนเต็มของฉันใช้เวลา 13 ~ 14 ชั่วโมงโดยมีการถ่ายโอนข้อมูล 35GB (gziped)

/pattern/,/pattern/pกับ-nพารามิเตอร์ทำให้ชิ้น "ระหว่างรูปแบบ" - รวมถึงพวกเขา

อย่างไรก็ตามเพื่อเรียกคืน 35GB ฉันใช้เครื่อง AWS EC2 (c3.8x ใหญ่) ติดตั้ง Percona ผ่าน yum (Centos) และเพิ่งเพิ่ม / เปลี่ยนบรรทัดต่อไปนี้บนmy.cnf:

max_allowed_packet=256M
wait_timeout=30000

ฉันคิดว่าตัวเลขนั้นสูงเกินไป แต่ก็ใช้ได้สำหรับการตั้งค่าของฉัน


5

วิธีที่เร็วที่สุดในการนำเข้าฐานข้อมูลของคุณคือการคัดลอกไฟล์ (.frm, .MYD, .MYI) หาก MyISAM ไปยัง / var / lib / mysql / "ชื่อฐานข้อมูล" โดยตรง

มิฉะนั้นคุณสามารถลอง: mysql > use database_name; \. /path/to/file.sql

นั่นเป็นอีกวิธีในการนำเข้าข้อมูลของคุณ


1

วิธีหนึ่งที่จะช่วยให้การนำเข้าเร็วขึ้นคือล็อคตารางขณะนำเข้า ใช้ตัวเลือก --add-locks เพื่อ mysqldump

mysqldump --add-drop-table --add-locks --database db > db.sql

หรือคุณสามารถเปิดพารามิเตอร์ที่มีประโยชน์ด้วย- เลือกสิ่งนี้จะเปิดสิ่งที่มีประโยชน์สำหรับการถ่ายโอน

mysqldump --opt --database db > db.sql

หากคุณมีอุปกรณ์เก็บข้อมูลอื่นบนเซิร์ฟเวอร์ให้ใช้ - คัดลอกจากอุปกรณ์หนึ่งไปยังอีกอุปกรณ์หนึ่งเป็นวิธีการโอนถ่ายข้อมูลที่เร็วขึ้น

คุณสามารถกรองตารางที่ไม่ต้องการด้วย--ignore-table

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