Skip to Content
ภาพประกอบซีรีส์ร้านอะไหล่สมมติ แยกหน้าสินค้าสาธารณะ สมุดรายการ และงานรอทำ

เว็บเร็วขึ้น โตได้โดยไม่จ่ายเกินจำเป็น ตอนที่ 4: ฐานข้อมูลช้า แก้ที่คำถามก่อนเพิ่มสำเนา

อ่าน query plan คุม pool และแยกความสดของข้อมูล ก่อนเลือก replica หรือแบ่งข้อมูล
18 ตุลาคม ค.ศ. 2026 โดย
Tomz

ภาพปกสร้างด้วย AI เพื่ออธิบายร้านสมมติ ไม่ใช่ภาพระบบที่ติดตั้งหรือผลทดสอบจริง

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

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

เริ่มจากคำถามจริงและข้อมูลขนาดใกล้งานจริง

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

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

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

อ่านแผนการทำงานก่อนใส่ index ทุกคอลัมน์

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

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

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

คำถามจริง

รูปแบบ query และจำนวนครั้งต่อหน้าจอ

แผนจริง

ข้อมูลตัวแทน แถวที่อ่าน และเวลารอ

ผลต่อธุรกิจ

ความเร็วคู่กับสิทธิและความถูกต้อง

EXPLAIN ANALYZE รันคำสั่งจริง ต้องใช้ในขอบเขตที่ปลอดภัย ค่า cost ของ planner ไม่ใช่มิลลิวินาที
ภาพสมมติพนักงานใช้ภาพหัวเทียนค้นในลิ้นชักที่จัดหมวด ข้างกองเอกสารและบัตรอะไหล่ที่ยังไม่จัด
ภาพสมมติสร้างด้วย AI เปรียบการค้นตามหมวดกับการไล่หาในกองเอกสาร ใช้อธิบายแนวคิดการค้นข้อมูล ไม่ใช่ผลวัดความเร็วของ index

อ่านน้อยลงด้วยขอบเขตที่ผู้ใช้ต้องการ

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

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

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

Pool เป็นประตูคุมจำนวนคนเข้าทำงาน ไม่ใช่กำลังประมวลผลใหม่

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

รวมงบ pool ของแอปทุกเครื่อง worker งานเบื้องหลัง เครื่องมือรายงาน และช่วง deploy ด้วย ตัวอย่างในตอนก่อนที่แต่ละเครื่องมีเพดาน 20 connection ไม่ได้บอกว่าควรตั้งเท่านั้น ค่าที่เหมาะขึ้นกับจำนวนงานพร้อมกัน ต้นทุน query และเพดานฐานข้อมูล บางระบบใช้ pooler เพิ่ม แต่ต้องตรวจความเข้ากันได้ของ session และ transaction

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

Read replica อ่านได้เพิ่ม แต่ไม่ใช่คำตอบใหม่ทันทีทุกกรณี

Replica คือสำเนาที่ได้รับข้อมูลตามกลไกของฐานข้อมูล สามารถแยกงานอ่านบางประเภทออกจากเครื่องเขียนได้ แต่สำเนาที่อัปเดตแบบไม่รอพร้อมกันอาจตามหลัง ช่วงหลังการแก้ราคาหรือบันทึกคำสั่งซื้อ ลูกค้าอาจอ่านเจอข้อมูลก่อนแก้ถ้าระบบส่งการอ่านไปที่สำเนานั้นโดยไม่ดูข้อกำหนด

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

แหล่งเขียน

บันทึกธุรกรรมตามกติกา

ส่งและอัปเดต

มีช่วงเวลาที่ข้อมูลเดินทางและถูกนำไปใช้

แหล่งอ่าน

อาจยังเห็นก่อนแก้ตามรูปแบบ replication

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

การมี replica ยังไม่เท่ากับมีแผนกู้คืนครบ ต้องคิดถึงข้อมูลที่เสียหายแล้วถูกส่งตามไป วิธีเลือกปลายทางเมื่อเครื่องหลักเสีย การสูญข้อมูลที่ยอมรับได้ และเวลาที่กลับมาให้บริการ Backup กับการทดสอบ restore จึงยังมีหน้าที่ของตัวเอง การรายงานว่า backup สำเร็จไม่แทนหลักฐานว่ากู้ข้อมูลกลับมาใช้ได้

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

แบ่งข้อมูลเมื่อรู้ว่าจะลดการแย่งตรงไหน

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

ก่อนเลือกแนวทางนี้ ผมจะให้ทีมอธิบาย distribution key หรือกติกาแบ่งข้อมูล พร้อมแสดงกรณีที่หนักสุด ไม่ดูเฉพาะค่าเฉลี่ย การเลือกคีย์ตามร้านย่อยอาจแยกได้ดีเมื่อร้านมีขนาดใกล้กัน แต่ต้องมีทางรับมือร้านใหญ่มาก ย้ายข้อมูล และรักษาสิทธิข้ามส่วนด้วย

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

ตรวจผลด้วยงานที่ลูกค้าต้องจบ

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

ตรวจสต็อกแล้วเขียน ต้องกันการแข่งด้วย

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

Transaction ควรครอบงานที่ต้องสำเร็จร่วมกันอย่างพอดี ระวังการเปิดไว้ขณะรออีเมลหรือ API ภายนอกจนถือ lock นาน งานที่แยกไปทำภายหลังได้ต้องมีสถานะและการส่งต่อที่ไม่หาย ไม่ตัดเงื่อนไขความครบออกเพียงเพื่อให้เวลา query สั้นลง

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

Index ที่ตรงงาน

ช่วยค้นบางรูปแบบตามแผนที่วัด

ภาระที่ตามมา

พื้นที่ การเขียน สถิติ และบำรุงรักษา

จำนวน index หรือ replica ไม่ใช่คะแนนคุณภาพ เลือกจากภาระงานและตรวจความถูกต้องของธุรกรรมด้วย

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

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

อ่านต้นทางและขอบเขตของตัวอย่าง

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

แชร์บทความ

FacebookX
ภาพประกอบซีรีส์ร้านอะไหล่สมมติ แยกหน้าสินค้าสาธารณะ สมุดรายการ และงานรอทำ
เว็บเร็วขึ้น โตได้โดยไม่จ่ายเกินจำเป็น ตอนที่ 3: เพิ่มเครื่องแล้วต้องเพิ่มงานที่ทำสำเร็จได้จริง
เตรียมสถานะ การกระจายโหลด และกำลังเผื่อ ก่อนฝากการเติบโตไว้กับ autoscaling