แยกตารางใน MySQL การปฏิบัติที่ดี?


14

ฉันเริ่มทำงานกับโครงการที่มีอยู่และผู้พัฒนาคนก่อนหน้าได้แบ่งตารางออกเป็น 10 ตารางแยกกันด้วยสคีมาที่เหมือนกัน แต่มีข้อมูลต่างกัน

ตารางมีลักษณะดังนี้:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

คีย์หลักคือidฟิลด์จำนวนเต็ม แอปพลิเคชันใช้อัลกอริทึมแฮช ( idmod 10) เพื่อให้ทราบว่าตารางใดที่จะเข้าถึงเมื่อทำการค้นหา ตัวอย่างid= 10 [tableName_0]จะส่งผลให้

เมื่อรวมกันแล้วตารางอาจมี 100,000 แถวและอัตราการเติบโตค่อนข้างต่ำ

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

คำตอบ:


17

ฉันคิดว่าทุกคนกำลังทำสิ่งนี้มากเกินไป จุดสำคัญที่นี่คือ:

เมื่อรวมกันแล้วตารางอาจมี 100,000 แถวและอัตราการเติบโตค่อนข้างต่ำ

นี่เป็นเค้กชิ้นหนึ่งสำหรับ RDBMS ใด ๆ ที่จะจัดการ ไปกับตารางหนึ่งทำดัชนีให้ถูกต้องและพิจารณาว่าเป็นปัญหาที่แก้ไขแล้ว

คุณไม่จำเป็นต้องพิจารณาการแบ่งพาร์ติชันไม่ว่าจะเป็น "โฮมเมด" หรืออย่างอื่นจนกว่าคุณจะเริ่มจัดการกับข้อมูลจำนวนมาก - คิดพันล้านแถวขึ้นไป


3

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

ในระยะสั้นถ้าคุณใช้ 5.1+ คุณสามารถปล่อยให้ mysql ทำการแบ่งพาร์ติชันให้คุณได้ ดู http://dev.mysql.com/doc/refman/5.1/en/partitioning.html หากคุณใช้ 5.5 คุณควรตรวจสอบเอกสารเฉพาะเหล่านั้นเนื่องจากคุณจะพบความแตกต่าง

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

ตัวอย่างบางส่วน:

  • การบัคกิ้งแบบตรง (หรือการแฮ็ช) ขึ้นอยู่กับคีย์การค้นหาที่เข้าถึงบ่อย หากคุณกำลังมองหาคีย์หลักหรือคีย์เฉพาะอื่น ๆ อยู่เสมอ mysql สามารถลดพื้นที่การค้นหาลงได้โดยคำนึงถึงจำนวนพาร์ติชันที่คุณมี โปรดทราบว่านี่อาจเป็นอันตรายได้หากคุณแบ่งพาร์ติชันด้วยคีย์เดียวแล้วค้นหาด้วยคีย์อื่นบ่อยครั้ง หากคุณค้นหาด้วยคีย์ข้อมูลจะไม่ถูกแบ่งพาร์ติชันโดยจะต้องทำการค้นหาเพิ่มเติมในการค้นหา (หนึ่งรายการสำหรับแต่ละพาร์ติชัน b / c ตรงไปตรงมาจะไม่ทราบว่าข้อมูลอยู่ที่ไหน)
  • พิจารณาสถานการณ์ที่คุณมีระเบียนชั่วคราวที่เติบโตตามวันที่และคุณตัดออกเป็นเดือนที่แล้วเป็นระยะ หากคุณแบ่งพาร์ติชันตามวันที่คุณสามารถวางพาร์ทิชันที่เร็วพอ ๆ กับการวางโต๊ะไม่ว่าจะใหญ่แค่ไหน หากคุณต้องตัดตารางดังกล่าวตามวันที่คุณจะต้องออกแบบสอบถาม DELETE หนึ่งรายการขึ้นไปที่แต่ละแถวถูกลบ ข้อเสียของสิ่งนี้คือ mysql จะไม่สร้างพาร์ติชันใหม่โดยอัตโนมัติเมื่อคุณถึงวันที่สูงสุดที่คุณคิดไว้ในสถานการณ์นี้ คุณต้องการสคริปต์บำรุงรักษาพิเศษที่สร้างขึ้นในส่วนของคุณเพื่อเพิ่มพาร์ติชันตามที่จำเป็น
  • หากคุณใช้การตรวจสอบ myisam และการกู้คืนจะเร็วขึ้นมาก พิจารณาตาราง myisam 100G หากคุณต้องการกู้คืนตารางที่เสียหายคุณจะต้องมีพื้นที่ว่างบนดิสก์ประมาณ 100G เป็นอย่างน้อย หากมีการแบ่งพาร์ติชันออกเป็น 10 ชิ้นที่มีขนาดเท่ากันคุณต้องใช้พื้นที่ 10G เท่านั้น (และหน่วยความจำ key_sort_buffer น้อยลงเพื่อการกู้คืนที่รวดเร็ว); แต่จะต้องทำซ้ำสำหรับแต่ละพาร์ติชัน

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

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

แก้ไข

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


3

สิ่งที่ผู้พัฒนาก่อนหน้าได้ทำเพื่อคุณนั้นได้สร้างการใช้งานพาร์ติชันโดยแฮช MySQL รองรับสิ่งนี้จาก MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

ฉันไม่สามารถนึกถึงเหตุผลที่ดีได้ดังนั้นให้ใช้พาร์ติชันของคุณโดยแฮชแทนการใช้เวอร์ชันเนทีฟ [1] การดำเนินการเปลี่ยนแปลงสคีมาจะเป็นฝันร้าย

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

[1] อย่างไรก็ตามสำหรับพาร์ติชั่นประเภทอื่นบางประเภทคุณสามารถหมุนพาร์ติชั่นของคุณเองได้ MySQL บังคับให้คุณสร้างพาร์ติชันหลักของคุณในคีย์หลักและดัชนีเฉพาะทั้งหมด


2

ในการตอบคำถาม:

นี่เป็นวิธีแก้ปัญหาหรือไม่

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

ในการตอบคำถาม:

... หากเป็นการปฏิบัติที่ดีในทุกสถานการณ์

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

เช่นหลอกตารางบันทึกการใช้เว็บอาจมีรูปแบบ:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

โซลูชันของคุณสร้างตารางตามต้องการในฐานข้อมูลเว็บล็อก:

weblogs.20120301
weblogs.20120302
weblogs.20120303

เป็นต้น

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

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


0

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

ดังนั้นคำถามคือ: การแบ่งนั้นคุ้มค่ากับประสิทธิภาพหรือเป็นอันตรายต่อประสิทธิภาพหรือไม่

หากคุณมีธุรกรรมที่ต้องล็อคหลายแถวในหลายตารางและมีปัญหา (ตัวอย่างเช่นการหยุดชะงักหรือหมดเวลาธุรกรรม) คุณอาจต้องการรวมแถวเหล่านั้นไว้ในตารางเดียวและเขียน SQL ใหม่เพื่อแก้ไขปัญหา

เมื่อฉันคิดว่าจะแยกตารางฉันเคยพิจารณาถึงการแลกเปลี่ยนระหว่างประสิทธิภาพที่เพิ่มขึ้นกับความซับซ้อนของการเขียนโปรแกรม

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


0

เมื่อคุณต้องการจัดเก็บไฟล์ไว้ในตารางการใช้ metodology นี้ช่วยในการส่งออกซ่อมแซมและกู้คืน

ฉันมีตารางที่มี> 30 Gb แบ่งพาร์ติชันเป็น 10 ตาราง ตารางเหล่านี้มี ID - BLOB เท่านั้นและสำหรับฉันนั้นง่ายต่อการเก็บรักษา และฉันใช้ MyISAM เพื่อบันทึกบัฟเฟอร์ INNODB

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