MySQL โหลดข้อมูล INFILE ช้า 80% หลังจากป้อนกิ๊กเล็กน้อยด้วยเครื่องมือ InnoDB


14

ฉันกำลังโหลดไฟล์ 100GB ผ่าน LOAD DATA INFILE ฉันประสบความสำเร็จกับ MyISAM ไม่กี่ชั่วโมงและทำ

ฉันลองใช้ InnoDB ตอนนี้ โหลดเริ่มต้นอย่างรวดเร็วที่มากกว่า 10MB / วินาที (ดูการขยายไฟล์ตารางfile_per_tableเปิดอยู่)

แต่หลังจากนั้นประมาณ 5GB ของข้อมูลมันจะช้าลงเป็นช่วง 2-4MB / วินาทีเพราะฉันได้มากกว่า 20GB มันก็ลดลงประมาณ 2MB / วินาที

ขนาดบัฟเฟอร์พูล InnoDB คือ 8G และฉันได้ทำสิ่งต่อไปนี้ก่อนที่จะใช้คำสั่งโหลดข้อมูล INFILE:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

ฉันไม่เห็นเหตุผลที่มันเริ่มต้นได้ดีและช้าลงเมื่อเวลาผ่านไป

นอกจากนี้การใช้การตั้งค่าเดียวกันฉันใช้คำสั่งโหลดข้อมูล INFILE เดียวกันกับตารางโดยใช้ InnoDB และ MyISAM และชุดข้อมูลทดสอบ 5GB MyISAM เร็วกว่า 20 เท่า:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

มีอะไรอีกที่ฉันควรลองทำดู เครื่องยนต์ MyISAM สามารถติดตามอัตราการโหลดได้ดียิ่งขึ้น


รายละเอียดเพิ่มเติม:

  • ฉันพยายามโหลดไฟล์แยกทีละตัวไม่ต่างกัน

  • บังเอิญฉันมี 150 ไฟล์ 500MB ต่อไฟล์ภายในแต่ละไฟล์จะถูกจัดเรียงคีย์

  • หลังจากได้รับ 40GB ในชั่วข้ามคืน 12 ชั่วโมงต่อมาอัตราการโหลดลดลงเหลือ 0.5MB / วินาทีหมายความว่าการใช้งานเป็นไปไม่ได้

  • ฉันไม่พบคำตอบอื่น ๆ สำหรับคำถามที่คล้ายกันในฟอรัมอื่นดูเหมือนว่า InnoDB ไม่รองรับการโหลดข้อมูลจำนวนมากลงในตารางที่มีขนาดไม่กี่ GB

คำตอบ:


7

OBSERVATION # 1

autocommitผมสังเกตเห็นคุณปิด ที่จะซ้อนข้อมูลจำนวนมากใน ibdata1 ทำไม?

มีคลาสเจ็ด (7) ของข้อมูลที่เก็บไว้ใน ibdata1:

  • หน้าข้อมูลสำหรับตาราง InnoDB
  • หน้าดัชนีสำหรับตาราง InnoDB
  • พจนานุกรมข้อมูล
  • บัฟเฟอร์การเขียนซ้ำ
    • Safety Net เพื่อป้องกันการเสียหายของข้อมูล
    • ช่วย Bypass OS สำหรับการแคช
  • แทรกบัฟเฟอร์ (ปรับปรุงการเปลี่ยนแปลงดัชนีรอง)
  • ส่วนย้อนกลับ
  • เลิกทำการบันทึก
  • คลิกที่นี่เพื่อดูภาพแทน ibdata1

ข้อมูลบางอย่างถูกเปิดเผยในบางธุรกรรมขึ้นอยู่กับระดับการแยก การกระทำดังกล่าวสามารถผลิตล็อคคีย์หลักที่ไม่ได้ตั้งใจและข้อมูลจำนวนมากผี เมื่อสองสิ่งนี้เพิ่มขึ้นคุณควรคาดหวังว่าการชะลอตัวของงานจะช้าลง

คำแนะนำ:ปล่อยให้บันทึกอัตโนมัติบน

OBSERVATION # 2

ฉันเห็นคุณมีสิ่งนี้:

alter table item_load disable keys;

แป้นปิดการใช้งานไม่ได้ทำงานกับ InnoDB นี่คือเหตุผล:

  • MyISAM: DISABLE KEYSเพียงแค่ปิดการอัพเดตดัชนีรองสำหรับตาราง MyISAM เมื่อคุณแทรก INSERT ลงในตาราง MyISAM โดยที่คีย์ถูกปิดใช้งานจะส่งผลให้โหลดตารางอย่างรวดเร็วพร้อมกับสิ่งปลูกสร้างของคีย์หลักและดัชนีเฉพาะทั้งหมด เมื่อคุณเรียกใช้ดัชนีมัธยมศึกษาทั้งหมดจะถูกสร้างขึ้นเป็นเส้นตรงบนโต๊ะและผนวกเข้ากับENABLE KEYS.MYD
  • InnoDB: ตามที่แสดงในรูปภาพภายในของ InnoDB ระบบ tablespave ibdata1มีโครงสร้างเฉพาะสำหรับการแทรกดัชนีรอง ในปัจจุบันไม่มีข้อกำหนดในการจัดการดัชนีเหมือนกับ MyISAM

เพื่อแสดงสิ่งนี้ให้สังเกตความพยายามของฉันในการเรียกใช้ DISABLE KEYS บนตาราง InnoDB ใน MySQL

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

OBSERVATION # 3

คุณสังเกตเห็นว่า MyISAM โหลดเร็วกว่า InnoDB ถึง 20 เท่า คุณต้องการที่จะเร็วกว่า 24-25 เท่าหรือไม่ จากนั้นเรียกใช้สิ่งต่อไปนี้:

ALTER TABLE item_load ROW_FORMAT=Fixed;

นี้จะเพิ่มความเร็วแทรกครั้ง 20-25% โดยไม่ต้อง DDL การเปลี่ยนแปลงอื่น ผลข้างเคียง: ตาราง MyISAM สามารถเติบโตได้ขนาด 80% -100% ซึ่งอาจใหญ่กว่านี้

คุณสามารถทำงานนี้บนตาราง InnoDB เป็นอย่างดี แต่พฤติกรรมที่สอดคล้องกับกรดและMVCCของ InnoDB จะยังคงเป็นคอขวดของประสิทธิภาพการทำงานโดยเฉพาะอย่างยิ่งถ้าเขต VARCHAR ibdata1เพิ่มขึ้นอย่างมีนัยสำคัญจะถูกเขียนไปยัง


ข้อสังเกตสองข้อแรกคือสิ่งที่ฉันพยายามเพิ่มเพื่อแก้ไขปัญหาหลังจากที่ฉันสังเกตเห็นเป็นครั้งแรกความพยายามครั้งแรกของฉันคือการออกจาก innodb โดยลำพัง (เพียงแค่ปิดการบันทึกถังขยะ) ในการสังเกตครั้งที่ 3 ขนาดข้อมูลของฉันมีความยาวผันแปรสูงฉันคิดว่านี่จะเป็นปัญหาหรือไม่ ฉันรู้สึกเหมือนฉันแค่ต้องเก็บตาราง myisam นี้
David Parks

6

คำตอบสุดท้ายสำหรับคำถามนี้คือไม่ใช้ InnoDB สำหรับตารางอ้างอิงขนาดใหญ่ MyISAM กำลังกรีดร้องอย่างรวดเร็วใกล้กับปริมาณงานที่เพิ่มขึ้นของความเร็วดิสก์สำหรับการโหลดทั้งหมด InnoDB ก็หยุดทำงาน MyISAM นั้นเรียบง่าย แต่ในกรณีนี้ข้อกำหนดของตารางนี้ สำหรับตารางอ้างอิงอย่างง่ายที่โหลดจำนวนมากบนโหลดข้อมูล INFILE, MyISAM เป็นวิธีที่ดี

แต่โปรดทราบว่าหากคุณเรียกใช้ตาราง MyISAM และ InnoDB ทั้งคู่คุณจะต้องพิจารณาการจัดสรรหน่วยความจำสำหรับกลไกการแคช 2 กลไกแต่ละเอ็นจิ้นมีแคชเฉพาะของตัวเองซึ่งต้องมีการจัดสรรหน่วยความจำแยกต่างหาก


5

คุณสามารถลองแบ่งไฟล์อินพุตเป็นชิ้นเล็ก ๆ

ผมเองใช้http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html สำหรับเรื่องนี้

จะเกิดอะไรขึ้นถ้าคุณได้รับการล็อคตารางสำหรับตารางระหว่างการนำเข้า บางทีการล็อคระดับแถวของ InnoDB ทำให้ช้าลง (MyISAM ใช้การล็อคตาราง)

คุณสามารถอ่านแนวคิดเพิ่มเติมได้ที่นี่: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql


ไฟล์ของฉันมีขนาด 500MB อยู่แล้วฉันไปป์พวกเขาทั้งหมดผ่านไปป์ที่มีชื่อเดียวเพื่อให้การโหลดง่ายขึ้น แต่ฉันจะลองใช้วิธีนี้ทันที
David Parks

ไม่เห็นความแตกต่างที่นี่สวยเร็วฉันเห็นการลดความเร็วจาก 11MB / วินาทีการขยายตัวของไฟล์ DB เป็น 6MB (หลังจากประมาณ 2GB) ของข้อมูลและมันจะลดลงอย่างต่อเนื่อง ฉันกำลังโหลดไฟล์ทั้งหมดใน for for loop, การเรียก mysql แยกกัน
David Parks

ไฟล์แรกที่โหลดใน 54 วินาที, 2 ใน 3 ของ 39, 3 ใน 3 m9s, 4m7s, 5m21s และอื่น ๆ ไฟล์ทั้งหมด aprox ขนาดเดียวกัน
David Parks

2

หาก PK ของคุณไม่ใช่ AUTO_INCREMENT หรือข้อมูลในไฟล์ csv ที่ไม่เรียงลำดับบน PK มากกว่าที่อาจส่งผลต่อประสิทธิภาพของดาต้าโหลด เนื่องจากตารางใน MySQL เป็นดัชนีดังนั้นข้อมูลทั้งหมดจะถูกเก็บไว้ในลำดับที่เรียงหากค่า PK ไม่ได้อยู่ใน AUTO_INCREMENT กว่า MySQL จะต้องทำข้อมูลจำนวนมากเพื่อให้ได้ข้อมูลที่จัดเก็บในลำดับที่เรียง นี่คือเหตุผลสำหรับการโหลดข้อมูลที่ช้าลงเมื่อขนาดตารางเริ่มเพิ่มขึ้น

ฉันกำลังโหลดไฟล์ 91GB csv ที่มี PK ใน AUTO_INCREMENT โดยใช้ LOAD DATA INFILE และฉันไม่เห็นว่าการส่งผ่านข้อมูลของฉันลดลง ฉันได้เม็ดมีด 140K ถึง 145K ต่อวินาที ใช้ Percona MySQL 5.6.38

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