GORAGOD.com

query ด้วยการ join หรือ query ทีละตารางแบบไหนดีกว่ากัน

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

วิธีแรกเป็นการ query เพียงครั้งเดียวด้วยการ JOIN ได้ผลลัพท์ที่ต้องการจากการ query เพียงครั้งเดียว
SELECT P.`id`,P.`topic`,P.`auction_closed`,(P.`auction_closed`-1435483111AS `timeleft`,U.`email` 
FROM
 `bid_pramool_product` AS P 
INNER
 JOIN `bid_pramool_event` AS E ON E.`product_id`=P.`id` AND E.`action`=2 
INNER
 JOIN `bid_user` AS U ON U.`id`=E.`member_id` 
WHERE
 P.`auction_closed`<1435483411 AND P.`status`<2

ผลการทดสอบการประมวลผลจำนวน 10 ครั้ง ใช้เวลาเฉลี่ยในการประมวลผล (เอาแบบดูง่ายๆนะครับ ดูจากช่อง Elapsed) 160 ms. วิธีที่สองแตก query ออกเป็นสองส่วน
ครั้งแรก query เอาสินค้าที่ใกล้หมดเวลาออกมาก่อน
SELECT P.`id`,P.`topic`,P.`auction_closed`,(P.`auction_closed`-1435483050AS `timeleft` 
FROM `bid_pramool_product` AS P 
WHERE
 P.`auction_closed`<1435483350 AND P.`status`<2

ครั้งที่สอง เอารายการสินค้าใน query แรกไปหาสมาชิกที่ร่วมประมูล
SELECT E.`product_id`,U.`email` 
FROM
 `bid_pramool_event` AS E 
INNER
 JOIN `bid_user` AS U ON U.`id`=E.`member_id` 
WHERE
 E.`product_id` IN (3733,3736,3738AND E.`action`=2

ผลลัพท์การ query รวมทั้ง 2 คำสั่ง เฉลี่ยสัก 30 ms ละกัน จากผลการ query ทั้งสองวิธี จะเห็นว่าการแตก query ออกเป็นหลายๆอัน และจัดการด้วย PHP ร่วมด้วย ใช้เวลาในการประมวลผลน้อยกว่าการ query ด้วยการ JOIN ถึง 5 เท่า

ทั้งสองวิธีใช้หน่วยความจำในการประมวลผล พอๆกัน และ เมื่อรวมการประมวลผลด้วย PHP ด้วยแล้ว ก็ใช้เวลาในการประมวลผลไม่ต่างจากรายละเอียดด้านบนมากนัก
ข้อสังเกต ในผลการทดสอบนี้ ตาราง bid_pramool_event มีข้อมูลอยู่นับล้าน record (เอาจริงๆคือมันไม่สามารถเพิ่มข้อมูลได้แล้ว เนื่องจากมีข้อมูล id ถึง 2147483647 แล้ว) ดังนั้นผลการทดสอบนี้แสดงให้เห็นว่า หากข้อมูลที่นำมา JOIN มีเป็นจำนวนมาก การแยก Query จะทำให้ภาพรวมของระบบเร็วกว่า