เร่งการแปลง MyISAM เป็น InnoDB


15

ฉันมีเซิร์ฟเวอร์ mysql 5.1 ที่มีฐานข้อมูลประมาณ 450 ตารางกินพื้นที่ 4GB ตารางเหล่านี้ส่วนใหญ่ (ทั้งหมดยกเว้น 2) คือ MyIsam สิ่งนี้ได้ดีสำหรับส่วนใหญ่ (ไม่ต้องการธุรกรรม) แต่แอปพลิเคชันได้รับปริมาณการใช้งานและตารางบางอย่างได้รับผลกระทบเนื่องจากการล็อกตารางในการปรับปรุง นั่นคือเหตุผลที่ 2 ของตารางคือ InnoDB ตอนนี้

การแปลงในตารางที่เล็กกว่า (100k แถว) ไม่ใช้เวลานานเลยทำให้การหยุดทำงานน้อยที่สุด อย่างไรก็ตามตารางการติดตามของฉันบางส่วนกำลังเข้าใกล้ 50 ล้านแถว มีวิธีเพิ่มความเร็วALTER TABLE...ENGINE InnoDBในตารางขนาดใหญ่หรือไม่? และถ้าไม่มีวิธีอื่นในการแปลงการหยุดทำงานน้อยที่สุดในตารางเขียนหนักเหล่านี้?


1
สิ่งที่ต้องคำนึงถึง: คำถามหลายข้อในการโพสต์เดียวมักจะทำให้คนที่ไม่สามารถตอบคำถามอย่างใดอย่างหนึ่งจากการโพสต์คำตอบ
BenV

ฉัน VtC เนื่องจากค่อนข้างซับซ้อนในการตอบ คุณควรเปิดคำถามหลายข้อแยกกัน
jcolebrand

ฉันยินดีที่จะให้คำแนะนำเพื่อทำให้เป็นคำถามเดียว แต่จะแนะนำให้ลบคำถามนี้และเพิ่งเปิดใหม่หรือไม่ เขียนส่วนใหญ่จะเอาสอง 2 กระสุนและการเปลี่ยนแปลงครั้งแรก (ฉันปรับปรุงชื่อเช่นกันที่จะสะท้อนให้เห็นถึงที่เครื่องมือการเก็บรักษา)
ดีเร็กดาวนีย์

อาจจะไม่เป็นไร โดยปกติแล้วจะง่ายต่อการเขียนคำถามอีกสองข้อและลบคำถามนั้นออก อย่างไรก็ตามคุณสามารถปล่อยให้สิ่งนี้เป็น "อ้างอิง" ได้อย่างง่ายดายและให้อีกสองคนอ้างถึงกลับเป็นคำถาม "นี่คือเป้าหมายโดยรวมของฉัน"
jcolebrand

แก้ไขอันนี้ลงในหัวข้อย่อยหนึ่งหัวข้อจากนั้นโพสต์คำถามติดตามผล
Brian Ballsun-Stanton

คำตอบ:


10

ให้ฉันเริ่มต้นด้วยการพูดว่าฉันเกลียดการเปลี่ยนแปลง มันชั่วร้าย IMHO

สมมติว่านี่เป็นสคีมาตารางของคุณ -

CREATE TABLE my_table_of_love (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=MyISAM CHARSET=utf8;

นี่คือเส้นทางที่ฉันแนะนำ -

สร้างวัตถุตารางใหม่ที่จะแทนที่อันเก่า:

CREATE TABLE my_table_of_love_NEW (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=InnoDB CHARSET=utf8

แทรกแถวทั้งหมดจากตารางเก่าตามชื่อลงในตารางใหม่:

INSERT INTO my_table_of_love_NEW (id,my_value,date_created)
SELECT id,my_value,date_created FROM my_table_of_love;

ทดสอบการอพยพของควัน:

SELECT COUNT(*) FROM my_table_of_love_NEW;
SELECT COUNT(*) FROM my_table_of_love;
SELECT a.id,a.my_value,a.date_created FROM my_table_of_love_NEW a
LEFT JOIN my_table_of_love b ON (b.id = a.id)
WHERE a.my_value != b.my_value;

สลับชื่อตารางเพื่อให้คุณสามารถสำรองข้อมูลได้ในกรณีที่คุณต้องการย้อนกลับ

RENAME TABLE my_table_of_love TO my_table_of_love_OLD;
RENAME TABLE my_table_of_love_NEW TO my_table_of_love;

ดำเนินการทดสอบการถดถอย

วิธีการนี้เป็นที่นิยมมากขึ้นในตารางที่มีดัชนีหลายรายการและหลายล้านแถว

คิด?


1
ตกลง ... แม้ว่าจะเป็นธุรกรรมหนักคุณอาจจำเป็นต้องใช้ฐานข้อมูลลงในขณะที่ทำเช่นนี้ ( แต่ตารางการเปลี่ยนแปลงที่เกิดขึ้นเพื่อให้คุณได้เป็นระยะเวลานานของการหยุดทำงานมากที่สุด)
โจ

ใช่ฉันคิดว่ามันจะต้องหยุดทำงานสำหรับตารางที่ใช้งานมากขึ้น ฉันจะต้องทำการทดสอบ แต่ทำไมจะALTER TABLEใช้เวลานานกว่าINSERT INTO...SELECT50 ล้านแถว?
Derek Downey

มันจะไม่ โดยทั่วไปแล้ว MySQL จะทำสิ่งภายในอย่างที่ผู้โพสต์แนะนำ มันสร้างสำเนาของคำจำกัดความและหยดโหลดลงในสำเนา
Morgan Tocker

ฉันชอบวิธีนี้เพราะข้ามส่วน "คัดลอกไปยัง tmp" ซึ่งอาจใช้เวลาสักครู่สำหรับตารางขนาดใหญ่
Haluk

ให้ฉันเพิ่มตอนนี้ใน MySQL 5.7, ALTER จะเร็วและง่ายต่อการจัดการ
Randomx

7

1) การป้องกันความสูญเสียเป็นหน้าที่ของความหวาดระแวง ทำการสำรองข้อมูลเสมอ หากคุณหวาดระแวงจริงๆให้ทำการสำรองข้อมูลจากนั้นเรียกคืนจากการสำรองข้อมูล

2) หน้านี้ของคู่มือ MySQL มีคำแนะนำในการแปลงประเภทตาราง

วิธีที่เร็วที่สุดในการเปลี่ยนตารางเป็น InnoDB คือการแทรกลงในตาราง InnoDB โดยตรง นั่นคือใช้ ALTER TABLE ... ENGINE = INNODB หรือสร้างตาราง InnoDB ที่ว่างเปล่าที่มีนิยามเหมือนกันและแทรกแถวด้วย INSERT INTO ... SELECT * จาก ...

3) PostgreSQL ทำการค้นหาข้อความแบบเต็ม The Sphinx Engine ดูเหมือนจะใช้กับ MySQL


ฉันจะดูเป็นสฟิงซ์อย่างแน่นอนเพราะฉันเพิ่งได้ยินเรื่องนี้
Derek Downey

3

มันง่ายกว่า X ที่จะเพิ่มประสิทธิภาพเซิร์ฟเวอร์ทั้งหมด (การกำหนดค่าหน่วยความจำแคชดัชนี) เมื่อคุณใช้เอ็นจินเดียวเท่านั้น การผสม myisam กับ innodb บนฐานข้อมูลขนาดใหญ่มักจะติดอยู่ที่จุดบังคับโดย comprosise บางอย่างเพื่อให้เอ็นจิ้นทั้งสองทำงานได้ดี (แต่ไม่เก่ง :)

ฉันขอแนะนำให้คุณให้ความสนใจในเครื่องมือค้นหาข้อความแบบเต็มเฉพาะเช่นsphinx , lucene ( solr ) และกำจัดมันออกจากเลเยอร์ฐานข้อมูล

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