การลบและเรียกคืนพื้นที่จากตาราง InnoDB


14

ฉันมีตาราง InnoDB 700GB ซึ่งฉันไม่ได้เขียนข้อมูลใด ๆ เพิ่มเติมไปยัง (อ่านเท่านั้น) ฉันต้องการลบข้อมูลเก่าที่เก็บไว้และเรียกคืนพื้นที่ดิสก์นั้น (ขณะที่ฉันหมดข้อมูล) ส่วนลบนั้นค่อนข้างง่ายเพราะฉันมีดัชนีหลักอัตโนมัติเพื่อให้ฉันสามารถวนซ้ำโดยใช้มันและลบแถว แต่นั่นจะไม่ทำให้ฉันกลับมามีพื้นที่อีก ฉันคิดว่าOPTIMIZE TABLEจะใช้ แต่อาจใช้เวลาตลอดไปบนโต๊ะ 700GB ดังนั้นมีตัวเลือกอื่นที่ฉันสามารถมองเห็นได้หรือไม่

แก้ไขโดย RolandoMySQLDBA

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

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

เราต้องดูโครงสร้างของตารางด้วยหากได้รับอนุญาต

แก้ไขโดย Noam

นี่คือผลลัพธ์ของแบบสอบถาม:

datsize ndxsize tblsize
682.51 47.57 730.08

นี่คือโครงสร้างของตาราง ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

คุณมีไดรฟ์ข้อมูลดิสก์อื่นเพื่อจับข้อมูลเท่านั้นหรือไม่
RolandoMySQLDBA

@RolandoMySQLDBA ฉันมีฮาร์ดไดรฟ์ภายนอกที่ฉันสามารถติดตั้งได้ นั่นนับหรือไม่
Noam

@RolandoMySQLDBA แต่แน่นอนว่าต้องการตัวเลือกในการลบพื้นที่บางส่วนโดยไม่จำเป็นต้องมีอีก 700GB
Noam

@RolandoMySQLDBA ขนาดของดิสก์เพิ่มเติมทำให้เกิดปัญหาประสิทธิภาพหรือไม่
Aris

@Aris อาจขึ้นอยู่กับดิสก์และเวลาในการค้นหา วันนี้ดิสก์ส่วนใหญ่ทำงานได้ดีขึ้นในตอนนี้ แต่สิ่งที่ดีคือการสูญเสียรอบ (แม้จะเร็วมาก ๆ ) ถ้าคุณมีช่องว่างขนาดใหญ่ในตารางของคุณ นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งสำหรับ InnoDB ซึ่งโดยปกติแล้วจะถูกแก้ไขที่บล็อก 16K ด้วยการแบ่งแฟรกเมนต์ภายในบล็อก 16K คุณอาจต้องการจัดระเบียบตารางโดยใช้ALTER TABLE ... ENGINE=InnoDB;(ถ้าคุณมีห้องที่จะทำ) ส่วนใหญ่พอใจกับ SSD ที่เร็วมากและไม่ต้องกังวลอีกต่อไป
RolandoMySQLDBA

คำตอบ:


21

นี่เป็นคำถามที่ดี คุณมีวิธีแก้ปัญหาหลายอย่าง แต่ตารางของคุณค่อนข้างใหญ่ดังนั้นจะไม่มีใครเจ็บปวด :)

คุณมีวิธีแก้ไขสามวิธีในการ "ลดขนาด" ตาราง InnoDB:

1. ปรับตารางให้เหมาะสม

คุณสามารถใช้OPTIMIZE TABLEตามที่คุณพูดถึง แต่คุณควรใส่ใจกับinnodb_file_per_tableตัวแปร:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

ให้ฉันอธิบาย:

OPTIMIZE TABLEwhith ตาราง InnoDB ล็อคตารางคัดลอกข้อมูลในตารางใหม่สะอาด (ว่าทำไมผลที่ได้คือ shrinked) วางตารางเดิมและเปลี่ยนชื่อตารางใหม่ที่มีชื่อเดิม นั่นเป็นสาเหตุที่คุณควรใส่ใจที่จะเพิ่มปริมาตรสองเท่าของตารางของคุณไว้ในดิสก์ของคุณ (ในระหว่างการดำเนินการคุณจะต้องมี 2x700GB)

เมื่อคุณอยู่ใน innodb_file_per_table = ON ตารางทั้งหมดมีไฟล์ข้อมูลที่เหมาะสม ดังนั้นOPTIMIZEคำสั่งจะสร้างไฟล์ข้อมูลใหม่ (~ 700GB) เมื่อการดำเนินการเสร็จสิ้น MySQL จะวางไฟล์ต้นฉบับและเปลี่ยนชื่อไฟล์ใหม่ (ดังนั้นในตอนท้ายของ 700GB - อาจน้อยกว่าเพราะมันจะถูกย่อขนาด - ของข้อมูล สร้างขึ้นในระหว่างการดำเนินการจะถูกปล่อยออกมา

เมื่อคุณอยู่ใน innodb_file_per_table = OFF ข้อมูลทั้งหมดไปที่แฟ้มข้อมูลที่หนึ่ง: ibdata ไฟล์นี้มีลักษณะเฉพาะที่น่าเศร้ามันไม่สามารถย่อขนาดได้ ดังนั้นในระหว่างOPTIMIZEกระบวนการตารางใหม่ของคุณจะถูกสร้างขึ้น (ใกล้ 700GB) แต่แม้หลังจากการดำเนินการปล่อยและเปลี่ยนชื่อ (และจุดสิ้นสุดของOPTIMIZEช่วง) ibdataของคุณจะไม่ปล่อย ~ 700GB ดังนั้นคุณต้องการข้อมูลฟรี แต่คุณมี 700GB มากกว่าเจ๋งใช่มั้ย

2. แก้ไขตาราง

นอกจากนี้คุณยังสามารถใช้ALTER TABLEคำสั่งที่จะทำงานในลักษณะเดียวกับที่ALTER TABLE OPTIMIZE TABLEคุณสามารถใช้:

ALTER TABLE myTable EGINE=InnoDB;

3. แก้ไขตาราง (ออนไลน์)

ปัญหาของOPTIMIZEและALTER TABLEมันล็อคตารางในระหว่างการดำเนินการ คุณสามารถใช้เครื่องมือ Percona: pt-online-schema-change (จากลิงก์ Percona Toolkit: ลิงก์ ) pt-online-schema ... จะสร้าง mecanism ด้วยทริกเกอร์และตาราง temp ที่คุณอนุญาตให้ตารางต้นฉบับพร้อมใช้งานสำหรับการอ่านและเขียนในระหว่างการดำเนินการ ฉันใช้เครื่องมือนี้ในการผลิตสำหรับตัวใหญ่ALTERมันเจ๋งมาก

โปรดทราบว่าคุณควรFOREIGN KEYอ้างอิงตารางของคุณ FK และก่อให้เกิดความเสี่ยงในการสร้างความยุ่งเหยิง ในการตรวจสอบข้อกำหนดเบื้องต้นนี้ให้ค้นหา:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

นี่คือวิธีที่ฉันใช้ pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

โปรดทราบว่าบันทึกย่อของฉันใน innodb_file_per_table นั้นเป็นจริงสำหรับวิธีนี้เช่นกัน

4. mysqldump

ทางออกสุดท้ายคือการสร้างฐานข้อมูลทั้งหมดจากการถ่ายโอนข้อมูล ยาวชะมัด แต่มีประสิทธิภาพมาก โปรดทราบว่านี่เป็นทางออกเดียวในการ "ย่อขนาด" ไฟล์ ibdata

แม็กซ์


นอกจากนี้ในเครื่องมือออนไลน์ percona แก้ไขตัวเลือกตารางฉันจะต้อง 700GB ของพื้นที่ว่างในดิสก์?
โนม

ใช่ pt-online แค่ใช้ mecanism เพื่อทำ ALTER ออนไลน์ แต่มันก็ทำให้ ALTER อยู่ดี
Maxime Fouilleul

@MaximeFouilleul ขนาดของดิสก์เสริมทำให้เกิดปัญหาประสิทธิภาพหรือไม่
Aris

1

ถ้าคุณมีขนาดดิสก์สั้นฉันขอแนะนำให้คุณทำเช่นเดียวกับ Max ที่แนะนำกับ pt-online-schema-change (ONLINE) ฉันอยู่ในสถานการณ์เดียวกันกับโต๊ะขนาดเล็ก (200GB) และเลือกที่จะทำการบีบอัดบางอย่างในเวลาเดียวกัน บางสิ่งในแนวนี้ควรใช้งานได้:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

สิ่งนี้จะใช้งานได้หากคุณอยู่ในรูปแบบไฟล์ Barracuda และในรูปแบบ COMPACT ของตาราง นอกจากนี้คุณต้องเปิดใช้งาน innodb_file_per_table สิ่งนี้สามารถสร้างความประหลาดใจให้กับขนาดของตารางของคุณโดยเฉพาะอย่างยิ่งหากมีข้อความจำนวนมากและหากคุณใช้ KEY_BLOCK_SIZE ที่เล็กลงเช่น 8K หรือแม้แต่ 4K (ค่าเริ่มต้นคือ 16K) นอกจากนี้คุณยังสามารถตรวจสอบจำนวนพื้นที่ที่คุณจะได้รับจากการวัดประสิทธิภาพหลาย ๆ อันเกี่ยวกับปัญหานี้ในบล็อกอื่น ๆ แต่เอกสาร MySQL ประกาศโฆษณา 25% ถึง 50% (สำหรับฉันเกือบ 90%)

โปรดทราบว่าสิ่งนี้สามารถส่งผลต่อประสิทธิภาพเมื่อทำการเลือก (จากเอกสารคู่มือ MySQL):

ดังนั้นในเวลาใดก็ตามบัฟเฟอร์พูลอาจมีทั้งรูปแบบที่บีบอัดและไม่บีบอัดของหน้าหรือเฉพาะรูปแบบที่บีบอัดของหน้าหรือไม่

MySQL ยังต้องคลายการบีบอัดข้อมูลเมื่อไม่ได้อยู่ในกลุ่มบัฟเฟอร์ ดังนั้นได้รับคำเตือน

มันใช้งานได้ดีจริง ๆ ในกรณีของฉัน ฉันมีข้อความยาว 200GB กลายเป็น 26GB การแสดงไม่เปลี่ยนแปลง

สำหรับข้อมูลเชิงลึกเพิ่มเติมตรวจสอบลิงค์เหล่านี้:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

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