ThaiSEOBoard.com

พัฒนาเว็บไซต์ => Programming => ข้อความที่เริ่มโดย: xmen256k ที่ 11 กรกฎาคม 2013, 21:51:24



หัวข้อ: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: xmen256k ที่ 11 กรกฎาคม 2013, 21:51:24
มีเรคคอร์ดอยู่ประมาณ 10,000 อัน และมีสถานะกำกับอยู่

ผมอยากจะสุ่มข้อมูลมาโชว์ 1 อันครับ

ไม่ทราบว่า เขียน SQL ยังไงให้คิวรี่ได้เร็วและไม่หนักโฮสบ้าง

ปล.
ผมลอง
โค๊ด:
SELECT * FROM table WHERE status ='correct' ORDER BY RAND() LIMIT 1 

มันช้าอ่าครับ

ขนาดรันใน localhost ใช้เวลาไป 993ms

รบกวนหน่อยนะครับ

ขอบคุณครับ


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: mikeyx ที่ 11 กรกฎาคม 2013, 21:56:51
โค๊ด:
SELECT filed1,filed2,.... FROM table WHERE status ='correct' ORDER BY RAND() LIMIT 1

ทำ index
เวลา query ให้ query ตรง ๆไปเลย เช่น
$query_tb = mysql_query("SELECT filed1,filed2,.... FROM table WHERE status ='correct' ORDER BY RAND() LIMIT 1");
$show_data = mysql_fetch_array($query_tb);


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: Bigguide ที่ 11 กรกฎาคม 2013, 22:01:52
1.ทำ index ให้ field "status" ดูครับ
2. ถ้า Query เราช้า ให้ลองใช้ explain ดูนะครับ จากตัวอย่าง query คุณ ใช้เป็น
explain SELECT * FROM table WHERE status ='correct' ORDER BY RAND() LIMIT 1



หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: goldxp ที่ 11 กรกฎาคม 2013, 22:41:19
SELECT * FROM table WHERE status ='correct' ORDER BY RAND() LIMIT 1
ผมใช้เครื่องpc รุ่นซื้อมา 7 ปีแล้ว run ยังแค่ 16-50 ms ครับ
ถ้าต้องการให้เร็วขึ้นลอง

set @number = (select max(id) from `table`)*rand();
select * from `table` where status='correct' and id > @number limit 1;

อันนี้ใช้เวลาใกล้เคียงกันครับ น่าจะแล้วแต่ว่าเครื่องกำลังทำงานอย่างอื่นด้วยหรือเปล่าซึ่งจะทำให้ช้าลงด้วยครับ  :P


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: MapTwoZa ที่ 12 กรกฎาคม 2013, 01:39:42
ถ้า data เยอะๆ order by rand() ไม่ดีแน่ๆครับ ห้ามใช้เด็ดขาดไอ order by rand() อ่ะ


ให้ใช้วิธี random ใน php แล้วไป query เอาครับ เช่นให้ใช้วิธี random ใน php แล้วไป query เอาครับ เช่น
$minId = rand(0,10000);
$result = mysql_query("SELECT * FROM `table` where id>$minId LIMIT 1");
** ใช้ > เพื่อกัน missing row ในกรณีเป็น auto increase
**** วิธีนี้ต้องรู้ range ของ data ที่แน่นอนครับ


แต่ถ้าข้อมูลไม่นิ่ง มีเพิ่มเรื่อยๆ ก็ให้ใช้วิธีนี้ครับ
สร้างตารางเป็น memory engine เอาไว้เก็บผลการ random ครับ วิธีนี้จะช้าตอนที่ query ครั้งแรก กับตอน data ในอีก table หมดครับ
เช่น ตาราง table กับ tablerand
โค๊ด:
function queryRandom(){
   $result = mysql_query("select tr.*, (select min(tr2.trid) as mini from tablerand tr2) from tablerand tr where tr.trid = mini");
   if(mysql_num_rows($result)==0){
      prepareData();
      return queryRandom();
   }
   else{
      // delete from tablerand where id = mini
      return ...; // return result of the query
   }
}
function prepareData(){
   // insert into tablerand select null as trid, t.* from table t order by rand() limit 100-1000
}
ตรงไหนเป็น comment ก็ไปเพิ่ม code เอาเองนะครับ


** ตาราง table rand ให้มี trid เป็น pk auto increase นะครับ

ปล. วิธีที่ 2 อาจจะช้าก็ได้นะ แค่ลองคิดแปลกๆ 55+ แต่คิดว่าน่าจะไวเพราะเอา memory engine มาใช้กับอีกตาราง


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: Nomkhonwaan ที่ 12 กรกฎาคม 2013, 08:32:08
เป็นผมน่ะ

query รอบแรกดึงจำนวน record ทั้งหมดออกมาดูว่ามีกี่ record

จากนั้นใช้ php rand() ตัวเลขจากจำนวน record ทั้งหมด แล้ว query รอบสองก็ใช้ limit, offset เอา

เช่นสมมติดึงได้ 10k records ก็สั่ง rand()&10000 มันก็จะ random ตัวเลขระหว่าง 0 - 10000 ออกมา

ก็เอาไป query แบบนี้

โค๊ด:
$offset = rand()&(10000 - 1)
SELECT * FROM `table` WHERE `condition` .... LIMIT $offset, 1

 :wanwan020:


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: teerdear1 ที่ 12 กรกฎาคม 2013, 08:42:53
ถ้าผมจำไม่ผิด ถ้ามีข้อมูลเป็นแสน แล้วใช้คำสั่ง limit 1
เปลี่ยนเป็น fetch ข้อมูลมาครั้งเดียวจะไวกว่านะครับ ถ้าจำไม่ผิดอ่านะ


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: phurich ที่ 12 กรกฎาคม 2013, 13:25:25
จำเป็นต้องใช้ SQL เท่านั้นเหรอครับ? หาก function Rand() ของ SQL มันช้า ก็ไปหา Algorithm อื่น ของภาษาอื่นมาก็ได้ครับ

ลองหา Algorithm การสุ่มค่าที่เร็วที่สุดในโลกดู พอได้แล้ว ก็ให้มันสุ่มเลขขึ้นมา แล้วคุณก็เอาเลขนั้น ไป select ข้อมูลเลย


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: xmen256k ที่ 12 กรกฎาคม 2013, 20:36:37
เป็นผมน่ะ

query รอบแรกดึงจำนวน record ทั้งหมดออกมาดูว่ามีกี่ record

จากนั้นใช้ php rand() ตัวเลขจากจำนวน record ทั้งหมด แล้ว query รอบสองก็ใช้ limit, offset เอา

เช่นสมมติดึงได้ 10k records ก็สั่ง rand()&10000 มันก็จะ random ตัวเลขระหว่าง 0 - 10000 ออกมา

ก็เอาไป query แบบนี้

โค๊ด:
$offset = rand()&(10000 - 1)
SELECT * FROM `table` WHERE `condition` .... LIMIT $offset, 1

 :wanwan020:

คือผมก็คิดไว้แบบนี้อ่าครับ แต่มันจะมีปัญหาหรือเปล่า

สมมติว่าถ้าช่วงฟิวของ auto increasment มันขาดตอนเช่น 1 2 3 5 6 7

แล้วแรนดอมออกมาเป้น 4 มันจะไปอ้างอิง ฟิว นั้นได้ยังไงอ่าครับ ??


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: sskzclub ที่ 12 กรกฎาคม 2013, 21:54:49
เข้ามาติดตาม ครับ ^^


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: xmen256k ที่ 13 กรกฎาคม 2013, 02:47:50
เป็นผมน่ะ

query รอบแรกดึงจำนวน record ทั้งหมดออกมาดูว่ามีกี่ record

จากนั้นใช้ php rand() ตัวเลขจากจำนวน record ทั้งหมด แล้ว query รอบสองก็ใช้ limit, offset เอา

เช่นสมมติดึงได้ 10k records ก็สั่ง rand()&10000 มันก็จะ random ตัวเลขระหว่าง 0 - 10000 ออกมา

ก็เอาไป query แบบนี้

โค๊ด:
$offset = rand()&(10000 - 1)
SELECT * FROM `table` WHERE `condition` .... LIMIT $offset, 1

 :wanwan020:

คือผมก็คิดไว้แบบนี้อ่าครับ แต่มันจะมีปัญหาหรือเปล่า

สมมติว่าถ้าช่วงฟิวของ auto increasment มันขาดตอนเช่น 1 2 3 5 6 7

แล้วแรนดอมออกมาเป้น 4 มันจะไปอ้างอิง ฟิว นั้นได้ยังไงอ่าครับ ??

ผมพอเข้าใจหละครับ

ตอนนี้ก็ลองทำดูแล้ว ลดลงเหลือ อยู่ราวๆ 50 ms

ปัญหาต่อมาคือผมจะสุ่มมากกว่า 1 อันอ่าครับ

ซึ่งลองเปลี่ยน LIMIT xxx,1 จาก 1 เป็น 5 ดู

มันกลับให้เป็นข้อมูลที่เรียงลงมากัน

ถ้าเป็นไอดีก็จะได้  4 5 6 7 8 อะไรแบบนี้

ถ้าอยากทำแบบสุ่ม 5 ตัว พอจะมีแนวทางบ้างไหมครับ


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: cloudsphere ที่ 13 กรกฎาคม 2013, 09:49:23
เข้ามาเก็บข้อมูล  :wanwan003: :wanwan017:


หัวข้อ: Re: [PHP,SQL] จะ random เรคคอร์ดอย่างไรให้รวดเร็ว ???
เริ่มหัวข้อโดย: คนธรรมดา ที่ 13 กรกฎาคม 2013, 10:55:57
เป็นผมน่ะ

query รอบแรกดึงจำนวน record ทั้งหมดออกมาดูว่ามีกี่ record

จากนั้นใช้ php rand() ตัวเลขจากจำนวน record ทั้งหมด แล้ว query รอบสองก็ใช้ limit, offset เอา

เช่นสมมติดึงได้ 10k records ก็สั่ง rand()&10000 มันก็จะ random ตัวเลขระหว่าง 0 - 10000 ออกมา

ก็เอาไป query แบบนี้

โค๊ด:
$offset = rand()&(10000 - 1)
SELECT * FROM `table` WHERE `condition` .... LIMIT $offset, 1

 :wanwan020:

คือผมก็คิดไว้แบบนี้อ่าครับ แต่มันจะมีปัญหาหรือเปล่า

สมมติว่าถ้าช่วงฟิวของ auto increasment มันขาดตอนเช่น 1 2 3 5 6 7

แล้วแรนดอมออกมาเป้น 4 มันจะไปอ้างอิง ฟิว นั้นได้ยังไงอ่าครับ ??

ผมพอเข้าใจหละครับ

ตอนนี้ก็ลองทำดูแล้ว ลดลงเหลือ อยู่ราวๆ 50 ms

ปัญหาต่อมาคือผมจะสุ่มมากกว่า 1 อันอ่าครับ

ซึ่งลองเปลี่ยน LIMIT xxx,1 จาก 1 เป็น 5 ดู

มันกลับให้เป็นข้อมูลที่เรียงลงมากัน

ถ้าเป็นไอดีก็จะได้  4 5 6 7 8 อะไรแบบนี้

ถ้าอยากทำแบบสุ่ม 5 ตัว พอจะมีแนวทางบ้างไหมครับ

ทำได้แล้วก็ใช้วิธี Loop