จัดการฐานข้อมูลขนาดใหญ่ด้วย Table Partitioning
ฐานข้อมูลขนาดใหญ่มากๆมีเป็นล้านๆแถว ปัญหาคือดูแลยาก จะเพิ่มจะลบวุ่นวายมากสิ่งที่จะมาช่วยเราจัดการเรื่องนี้คือ partition ซึ่งเป็นของใหม่ใน postgres 11
ปัญหาของเราคือการดึงข้อมูลจากตารางที่มีข้อมูลเยอะมาก ดังนั้นการแก้ปัญหาแบบง่ายๆคือให้เราแยกตางรางเป็นตารางย่อยๆแทน แต่การแยกตารางย่อยๆก็ทำให้ดูแลยาก หากมีการอัพเดทตารางเช่นเพิ่มคอลัมน์เข้าไปเราต้องไปไล่แก้ทุกๆตารางยุ่งยาก บักเยอะแน่นอน ดังนั้นวันนี้เราจะมาพูดถึงวิธีการแยกตารางแต่ระบบยังมองเห็นเป็นตารางเดียวกันอยู่นั้นคือการทำ partition
การทำ partition คือการแยกตารางใหญ่เป็นตารางย่อยๆโดยที่ไม่ต้องสร้างตารางขึ้นมาจริงๆ แต่ใช้ระบบ partition เอา ตารางจะมีอยู่ 2 ประเภทคือ master, child ตาราง master คือตารางหลักเราจะแก้ไข ปรับปรุงเปลี่ยนแปลงให้ทำที่ตาราง master หลังจากนั้นข้อมูลจะไหลไปที่ child โดยอัตโนมัติ เวลาดึงข้อมูลก็จะดึงจาก child โดยอัตโนมัติเช่นเดียวกัน
การสร้างตาราง child จะมีอยู่ด้วยกัน 2 แบบคือ
1. range partitioning
คือการสร้างโดยให้ช่วงของข้อมูลเป็นตัวกำหนดว่าจะต้องสร้าง child table แบบไหน เช่นเราต้องการแบ่งข้อมูลตามเดือน ดังนั้นเราจะต้องสร้างฐานข้อมูลเพิ่มอีก 12 ตารางต่อการเก็บข้อมูล 1 ปี
2. list partitioning
คือการสร้างตารางโดยให้ความสำคัญของประเภทข้อมูลที่อยู่ด้านในเช่น เราต้องการแยกประเภทตามประเทศของคนที่เราเก็บไว้ เราก็จะต้องสร้างตารางอีก 195 อันเพื่อรองรับข้อมูลประเทศทั้งหมด
ถ้าเราสังเกตุดูจะพบว่าวิธีการเลือกว่าจะใช้แบบ range หรือ list ขึ้นอยู่กับว่าข้อมูลที่เราต้องการจะเก็บนั้นจะถูกดึงมาใช้แบบไหนถ้าเราจะดึงมาใช้ตามวันเวลาก็ควรใช้แบบ range หรือถ้าเอามาใช้ตามประเภทก็ควรใช้แบบ list เพื่อความเข้าใจที่ง่ายขึ้นมาดูภาพกันดีกว่า
ภาพจาก https://logicalread.com/partition-tables-sql-server-perf-dn01/#.XVjUB3UvOV4
ตารางสีดำคือตารางเก็บข้อมูลขนาดใหญ่ 10 ล้านแถว แต่เราได้สร้าง partition เอาไว้เพื่อแยกเก็บข้อมูลเหล่านี้ออกจากกัน โดยแบ่งตามเวลา ข้อมูลใน 1 ปีจะถูกแยกเก็บในตาราง 12 ตารางแยกออกจากกันโดยเด็ดขาด ทำให้แทนที่ข้อมูลจะถูกดึงจากตารางใหญ่เพียงอย่างเดียวทำให้ดึงได้ช้า แต่ระบบ partition จะแยกข้อมูลออกจากกันเป็นหลายๆตารางทำให้สามารถดึงข้อมูลได้เร็วกว่าเดิมมาก
แล้วถ้าจะใช้ต้องทำยังไง ตัวอย่างการเขียน sql ของ postgres
CREATE TABLE measurement ( id int not null, name string not null, date date not null, ) PARTITION BY RANGE (date);ตามตัวอย่างด้านบนเราสร้างตาราง measurement ขึ้นมาเป็นตาราง master จากนั้นเรากำหนดไปว่าให้มีการสร้าง partition โดยแบ่งข้อมูลตามวันเวลาที่เก็บ จากนั้นเราไปสร้างตาราง child ที่เหลือดังนี้
CREATE TABLE measurement_y2006m02 PARTITION OF measurement FOR VALUES FROM ('2006-02-01') TO ('2006-03-01'); CREATE TABLE measurement_y2006m03 PARTITION OF measurement FOR VALUES FROM ('2006-03-01') TO ('2006-04-01'); ... CREATE TABLE measurement_y2007m11 PARTITION OF measurement FOR VALUES FROM ('2007-11-01') TO ('2007-12-01'); CREATE TABLE measurement_y2007m12 PARTITION OF measurement FOR VALUES FROM ('2007-12-01') TO ('2008-01-01') TABLESPACE fasttablespace; CREATE TABLE measurement_y2008m01 PARTITION OF measurement FOR VALUES FROM ('2008-01-01') TO ('2008-02-01') WITH (parallel_workers = 4) TABLESPACE fasttablespace;
เราสร้างตาราง child โดยแยกเก็บตามระยะเวลา ดังนั้นใน 1 ปีเราจะเก็บข้อมูลเพิ่มเป็น 12 ตาราง
สรุป
คำถาม เวลาดึงข้อมูลต้องไปดึงจาก child หรือ ยุ่งตายชักเลยมีไม่รู้กี่ตาราง
ตอบ ดึงจากตาราง master อันเดียวเลยไม่ต้องยุ่งกับ child เลย ข้อมูลมันจะดึงมาจาก child เข้าหา master เองเราไม่ต้องไปยุ่งเลย
คำถาม นอกจากดึงข้อมูลเร็วแล้วมีอย่างอื่นอีกมั้ย
ตอบ มี เช่น เวลาเราต้องการจะลบข้อมูลใดๆก็ตามเราเลือกลบตารางได้เลย ไม่มีอะไรมาพัวพันกันให้ยุ่งยากเหมือนการเก็บในตารางเดียวแล้ว
คำถาม มีข้อจำกัดอะไรอีกมั้ย
ตอบ มีเยอะถ้าใช้ postgres 10 แต่ในภาค 11 เค้าจัดการข้อจำกัดให้หมดแล้ว โดยส่วนใหญ่ที่เกี่ยวกับการทำ index นะ
จบเรื่องของการทำ partitioning