การ query เอาจำนวนแถวจากตาราง แบบไหนน่าใช้กว่ากัน??
- Login to post comments
Sat, 2008-03-15 23:52
ในการ query เอาจำนวนแถวของข้อมูล จาก mysql standard functions เท่าที่ผมทราบ จะมีวิธีการอยู่ 2 ลักษณะ ด้วยกัน ได้แก่
วิธีที่ 1: SELECT *
<?php ... // some code $sql = "SELECT * FROM $myVeryBigTable WHERE $myCondition "; $rs = mysql_query($sql) or die("Some error occurred with DB: " . mysql_error()); $numRows = mysql_num_rows($rs); ... // some code ?>
วิธีที่ 2: SELECT COUNT(*) AS numRows
<?php ... // some code<br /> $sql = "SELECT COUNT(*) AS numRows FROM $myVeryBigTable " . "WHERE $myCondition "; $rs = mysql_query($sql) or die("Some error occurred with DB: " . mysql_error()); $row = mysql_fetch_array($rs); $numRows = $row['numRows']; ... // some code ?>
ทั้งสองวิธีไม่ได้ยุ่งยากอะไร และทำงานได้เหมือนๆ กัน แต่ลึกๆ แล้ว วิธีไหนมีประสิทธิภาพมากกว่ากัน กันแน่??? มีใครเคยทำวิจัย หรือ อ่านมามั้ยครับ??

แบบที่ 1 นั้นจะใช้ได้ดี ถ้าเรานับแล้วเอาข้อมูลที่ได้ไปใช้งานด้วย แต่ไม่แนะนำ ถ้าเอามาใช้แต่เฉพาะนับข้อมูลอย่างเดียว เพราะว่าต้องส่งข้อมูลมา count อย่างเดียวเปลือง i/o ของระบบครับ
แบบที่ 2 เป็นแบบที่แนะนำที่สุด สำหรับการนับข้อมูลอย่างเดียวล้วน ๆ เพราะส่งมาแค่ record และ field เดียวเท่านั้น แต่ถ้าใช้ storage engine ของ innoDB เค้าไม่แนะนำให้ใช้แบบนี้ครับ เพราะเร็วไม่เท่า MyISAM ในเรื่องของ Index และการ counting ครับ โดยใน documents ต่าง ๆ จะแนะนำให้ใช้ metadata ที่เก็บไว้แทน โดยใช้คำสั่ง "SHOW TABLE STATUS LIKE 'tablename';" จะ return ออกมาเป็น record เดียว แล้วไป fetch เอาแต่เฉพาะ field "Rows" ออกมาครับ จะเร็วกว่ามาก ๆ เลย จริง ๆ เป็นคำแนะนำสำหรับการ count อีกแบบที่ทำงานได้เร็วกว่า count ทั่วไปครับผม (ใช้ metadata แทนการ count ในข้อมูลจริงครับ)
เป็นคำแนะนำที่น่าสนใจมากครับ หลังจากตั้งคำถาม ผมก็มาพิจารณาจากการใช้งานจริงเหมือนกัน และนำคำแนะนำ ของคุณ Ford AntiTrust มาเป็นข้อมูลในการพิจารณาด้วย ผมขอแสดงความคิดเห็นเพิ่มเติม ดังนี้
1. ถ้าเรา SELECT * แล้วนำ result มาใช้งานต่อ คือ นอกจากจะนับจำนวนแถวแล้ว ก็นำ result ที่ได้ ไปทำงานต่อ เช่นเอาข้อมูลไปวนลูป ทำอะไรซักอย่างต่อ วิธีที่ 1 ก็น่าสนใจ เพราะถ้าเป็นวิธีที่ 2 ต้องทำการ query ถึง 2 ครั้ง
2. แต่สำหรับวิธีที่สอง จะเหมาะกับการนับจำนวนเพียงอย่างเดียว เช่นกรณีการจัด paging ของข้อมูล ที่ต้องนับจำนวนข้อมูลก่อน และเอามาคำนวนหา offset แล้วค่อยไป query เอาข้อมูลมาอีกที
และสำหรับการใช้ metadata แทนการนับข้อมูลจริง วิธีนี้ก็คงจะไวกว่าเพื่อนอย่างไม่น่าเชื่อ ^_^ แต่ว่า อาจจะมีข้อจำกัดอยู่บ้าง เช่น กรณีที่เราต้องการนับ แบบมีเงื่อนไข วิธีนี้ก็คงจะต้องข้ามไป
ขอบคุณสำหรับคำแนะนำของ Toyota เอ้ย! ของ Ford AntiTrust มากๆ คับ ผมได้มุมมองเพิ่มขึ้นมาอีกเยอะทีเดียว ทำให้ผมไม่ต้องไปทำวิจัยเองด้วย ^_^
ปล. ผมเล่นมุข เรียกชื่อผิดนี่ ไม่รู้คุณ Ford AntiTrust ถือหรือเปล่า ถ้าถือก็ต้องขออภัยน้ะคับ ^_^!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
เซือในสิ่งที่เฮ็ด เฮ็ดในสิ่งที่เซือ...
ไม่ถือหล่ะครับ โดนบ่อย ฮา ......
;P
เอ่อ ไม่ทราบ นะ
พยายามหา ข้อมูล แต่ ด้วยความอ่อนด้อย ทางด้าน ภาษาศาสตร์ ใช้ keyword ไม่โดน ใจ google เลย
เอ่อ ยังไง ก็ เห็นด้วยกับ การใช้ ไอเดียของ การใช้งาน metadata ถึงจะไม่ค่อยใช้ได้หลากหลายก็ เหอะ
แต่ก้ออยากรู้ ว่าจริงๆ มันจะเิป็นไง งไง กัน แน่อะไร ที่ แบบว่า เร็วสุดๆๆ ที่สุด กว่ากัน เหมือนกันคับ
ถ้าในระดับข้อมูลใน table ไม่เยอะมากนั้น การใช้ count(*) กับใช้ mysql_num_rows จะไม่ต่างกันมากครับ แต่ถ้า table ใหญ่ ๆ ระดับแสน หรือข้อมูลหลัก GB แล้วนี่่เห็นผลครับ และยิ่งใช้ metadata จะต่างกันแบบเห็น ๆ เลย ลอง simulate ข้อมูลสัก 10,000 - 1,000,000 หรือ 10,000,000 ดูครับ แล้วลองใช้ทั้ง 3 แบบจะเห็นความแตกต่างครับ
โดยจริง ๆ metadata นั้นถ้าใน mysql 4.1 เป็นต้นมาจะมี table "informaction_schema" อยู่ทุก ๆ access ครับ เราใช้ส่วนนั้นเป็นประโยชน์ได้ คือเจ้าของ informaction_schema เนี่ยเป็นตัวเก็บรายละเอียดทั้งหมดของ table และ database ที่เราม privilleges อยู่ครับ (ลองศึกษาดูครับ) ซึ่งถ้าเราใช้ส่วนนี้ให้เป็นประโยชน์ก็จะช่วยให้เอาข้อมูลของ table ออกมาได้รวดเร็วมาก เพราะมัน table เล็ก ๆ ครับ
ถ้าไล่ตามความเร็วแล้วก็ตามนี้ครับ
mysql_num_rows -> count(*) -> metadata
ช้า -> เร็ว
อ้าา
จริงๆ ด้วยคับ สารภาพอีก ว่า ก็ไม่เคยได้ ใช้ เหมือน ล่ะล่ะคับ
เดี่ยว พรุ่งนี้ลอง เลย
แล้วการใช้
COUNT(id) AS numRows
แทน
COUNT(*) AS numRows
โดย id เป็น primary key มันจะช่วยเรื่องเร็วได้อีกนิดหน่อยมั๊ยคะ
ปล. ไม่มีใครตอบกระทู้ปานนี่เลย หรือปานนี่ถามไม่รู้เรื่องอ่า (--")
การใช้ COUNT(id) AS numRows กับ COUNT(*) AS numRows มีผลไม่ต่างกัน (ลองแล้ว ^_^)
>> ปล. ไม่มีใครตอบกระทู้ปานนี่เลย หรือปานนี่ถามไม่รู้เรื่องอ่า (--")
ตอบให้แล้วน้ะคับ อันนี้หรือเปล่า?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
เซือในสิ่งที่เฮ็ด เฮ็ดในสิ่งที่เซือ...
COUNT(*) นี่เท่ากับ COUNT(pk) ครับ
ด้านล่างเอามาจาก MySQL Manual ครับ
COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause. For example:
mysql> SELECT COUNT(*) FROM student;