การ JOIN TABLE สำหรับฐานข้อมูลขนาดใหญ่
- Login to post comments
จะถามความคิดเห็นหน่ะค่ะกรณีที่เราต้อง join ข้อมูลจากหลายๆ table แล้วแต่ละ table มีข้อมูลหลักหมื่นหรือแสน rows ขึ้นไป
เคยเจอกรณี เช่น หาจำนวนสินค้าที่เหลืออยู่
SELECT prod_id, Count(*) as unit_remain FROM tb_account_stock WHERE prod_id=$prod_id AND SERIAL NOT IN (SELECT SERIAL FROM tb_account_sold) GROUP BY prod_id
ข้อมูลแต่ละtable มีขนาดใหญ่ ทำให้การคิวรี่ใช้เวลานานมาก แต่ถ้าแยกคิวรี่ออกมา 2 คิวรี่ แล้วเอามาลบกันก็จะได้จำนวนที่เหลืออยู่เหมือนกัน และเร็วกว่าด้วย
แล้วถ้าสมมุติเราจะทำเกี่ยวกะ report อะไรซักอย่าง
product 1 23 ตัว
product 2 50 ตัว
ถ้าการจะทำให้ได้ชื่อ product 1 ออกมา
กรณีที่ 1. ต้อง join table ประมาณ 3-4 table ซึ่งบาง table มีข้อมูลขนาดใหญ่ (อาจจะ where condition ธรรมดาด้วย ไม่ได้ not in เหมือนตัวอย่างข้างบน)
กรณีที่ 2. คือถ้าเราแยกคิวรี่หาชื่อ product ต่างหาก เราก็จะไม่ต้อง join กับ tableอื่นเลย
กรณี1 กับ 2 ใช้แบบไหนดีกว่ากัน
จำนวนข้อมูลที่เยอะๆ การ join มันจะมีผลกระทบเรื่องความเร็วเหมือนกรณีตัวอย่างข้างบนมั๊ยคะ
ปล. ใช้ theme ที่เป็น css แบบนี้บางทีเวลาข้อมูลหรือcode มันยาวๆ มันไม่ขยายตาม ข้อมูลมันก็ตัดไปมองไม่เห็นเลยอ่ะ
(เขียนโปรแกรมใครๆก็เขียนได้ แต่จะเขียนให้ดีมีประสิทธิภาพ มันไม่ง่ายนะ)
ขอแสดงความคิดเห็นส่วนตัวสักเล็กน้อยน้ะ
ก่อนอื่นชอบอันนี้จัง "เขียนโปรแกรมใครๆก็เขียนได้ แต่จะเขียนให้ดีมีประสิทธิภาพมันไม่ง่ายน้ะ" :D
ประเด็นที่ 1:
SELECT prod_id, Count(*) as unit_remain
FROM tb_account_stock
where prod_id=$prod_id and serial not in (SELECT serial FROM tb_account_sold)
group by prod_id
ลองมาพิจารณาการทำงานของมัน ... เนื่องจากมัน SELECT IN SELECT ทำให้การทำงานนั้น มันจะไป query ตัว sub-query ให้ได้ผลมาก่อน แลวเอาผลมาเป็นเงื่อนไขใน main-query ถ้า "SELECT serial FROM tb_account_sold" มันมีจำนวนเยอะมาก ก็เป็นธรรมดาที่มันจะอืด ลองคิดเล่นๆ ถ้าตาราง tb_account_sold มีข้อมูลอยู่ซักล้าน records "SELECT serial FROM tb_account_sold" มันจะมี output ออกมาถึง ล้านแถวเชียว ซึ่งล้านแถวนี้ อาจจะเป็น temp file เกิดขึ้นมา คิดดูว่ามันจะใช้ memory หรือ disk เยอะขนาดไหน และมันไม่แปลกที่จะช้าด้วย (เผลอๆ ถ้า disk space น้อยๆ temp ดังกล่าวอาจจะทำให้ disk เต็ม และระบบล่มก็ได้น้ะ หุหุ)
แต่ถ้าจำเป็นจะต้องใช้ "SELECT serial FROM tb_account_sold" นี้จริงๆ อาจจะต้องลองกลับไปดู ว่าจะเพิ่มเงื่อนไขเพื่อ filter ข้อมูลอีกได้หรือเปล่า เช่นอาจจะเอาเวลามาเป็นเงื่อนไขในการ filter ข้อมูล เป็นต้น
แต่เมื่อ query เอาจำนวนมาลบกัน ปานนี่พบว่า มันเร็วกว่ามากๆ อันนี้น่าจะเป็นวิธีที่ถูกต้องแล้ว เพราะว่า การนับ 2 ครั้ง มันจะมี output ขณะทำงาน ที่เล็กกว่า การ SELECT IN SELECT มากๆ
ประเด็นที่ 2:
ถ้าเป็นผม ผมเลือกวิธีที่ 2 คือ query เอาข้อมูลที่ต้องการก่อน แล้วค่อยมา markup เอาชื่อ หรือรายละเอียดของมันมา เพราะการ GROUP BY ข้อมูลที่เป็น KEY หรือ INDEX ซึ่งมักจะใช้ INT หรือ CHAR หรือ VARCHAR ที่มีขนาดไม่ใหญ่นัก จะไวกว่าการ GROUP BY ข้อมูลที่เป็น VARCHAR หรือ TEXT ที่เป็นชื่อ หรือ รายละเอียดของข้อมูล
ถึงแม้การ JOIN TABLE มันจะทำให้การเขียนโปรแกรมง่ายขึ้นมาก แต่มันก็ไม่ใช่คำตอบสุดท้ายของการเขียนโปรแกรม ควรใช้เท่าที่จำเป็น
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
การแก้ไขข้อผิดพลาดเป็นสิ่งที่ดี แต่การป้องกันข้อผิดพลาดนั้น ย่อมเป็นสิ่งที่ดีกว่า (แอบจำแบบผิดๆ ถูกๆ มาจากที่ทำงานเก่า :D)
>> ปล. ใช้ theme ที่เป็น css แบบนี้บางทีเวลาข้อมูลหรือcode มันยาวๆ
>> มันไม่ขยายตาม ข้อมูลมันก็ตัดไปมองไม่เห็นเลยอ่ะ
อันนี้ ผมก็เจอปัญหาอยู่เหมือนกัน ยิ่งมี "user profile ด้านซ้าย" ก็ยิ่งทำให้พื้นที่ในการแสดลข้อมูลน้อยลงไปอีก แต่มันก็ทำให้ forum มันดู user friendly ดี ยังงัยวิจารณ์กันมาได้เต็มที่น้ะคับ
โดยส่วนตัวผมเอง ก็ได้แต่ตัด code ตัวอย่างให้มันสั้นๆ มันจาได้ไม่เกินช่องแสดงข้อมูล อาศัยว่าเป็น forum ของโปรแกรมเมอร์ หวังว่าโปรแกรมเมอร์จะเข้าใจ :P แต่ทั้งนี้ทั้งนั้น ก็ไม่ได้นิ่งนอนใจน้ะคับ พี่ต้นกำลังหา solution อยู่ :D (โยนให้พี่ต้นซะงั้น)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
เซือในสิ่งที่เฮ็ด เฮ็ดในสิ่งที่เซือ...