MySQL查询随机数据的4种方法和性能对比
生活随笔
收集整理的這篇文章主要介紹了
MySQL查询随机数据的4种方法和性能对比
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
從MySQL隨機選取數據也是我們最常用的一種發發,其最簡單的辦法就是使用”ORDER BY RAND()”,本文介紹了包括ORDER BY RAND()的4種獲取隨機數據的方法,并分析了各自的優缺點。 下面從以下四種方案分析各自的優缺點。
方案一:
復制代碼 代碼如下: SELECT * FROM `table` ORDER BY RAND() LIMIT 0,1;
這種方法的問題就是非常慢。原因是因為MySQL會創建一張零時表來保存所有的結果集,然后給每個結果一個隨機索引,然后再排序并返回。
有幾個方法可以讓它快起來。
基本思想就是先獲取一個隨機數,然后使用這個隨機數來獲取指定的行。
由于所有的行都有一個唯一的id,我們將只取最小和最大id之間的隨機數,然后獲取id為這個數行。為了讓這個方法當id不連續時也能有效,我們在最終的查詢里使用”>=”代替”=”。
為了獲取整張表的最小和最大id,我們使用MAX()和MIN()兩個聚合函數。這兩個方法會返回指定組里的最大和最小值。在這里這個組就是我們表里的所有id字段值。
方案二:
復制代碼 代碼如下: <?php
$range_result = mysql_query( " SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM `table` ");
$range_row = mysql_fetch_object( $range_result );
$random = mt_rand( $range_row->min_id , $range_row->max_id );
$result = mysql_query( " SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
就像我們剛才提到的,這個方法會用唯一的id值限制表的每一行。那么,如果不是這樣情況怎么辦?
下面這個方案是使用了MySQL的LIMIT子句。LIMIT接收兩個參數值。第一個參數指定了返回結果第一行的偏移量,第二個參數指定了返回結果的最大行數。偏移量指定第一行是0而不是1。
為 了計算第一行的偏移量,我們使用MySQL的RAND()方法從0到1之間生成一個隨機數。然后我們把這個數字跟我們用COUNT()方法獲取倒的表記錄 數相乘。由于LIMIT的參數必須是int型而不能是float,我們使用FLOOR()來處理結果。FLOOR()會計算小于表達式的最大值。最終的代 碼就是這樣:
方案三:
復制代碼 代碼如下: <?php
$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `table` LIMIT $offset, 1 " );
在MySQL 4.1以后我們可以使用子子查詢合并上面兩個方法:
方案四:
復制代碼 代碼如下: SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;
這個方案跟方案二有同樣的弱點,只對有唯一id值的表有效。
記住我們最初尋找選擇隨機行的替代方法的原因,速度!所以,這些方案的在執行時間上的比較會怎么樣?我不會指出硬件和軟件配置或者給出具體的數字。大概的結果是這樣的:
最慢的是解決方案一(我們假定它用了100%的時間)。
方案二用了79%
方案三 – 13%
方案四 – 16%
so, 方案三勝出!
方案一:
復制代碼 代碼如下: SELECT * FROM `table` ORDER BY RAND() LIMIT 0,1;
這種方法的問題就是非常慢。原因是因為MySQL會創建一張零時表來保存所有的結果集,然后給每個結果一個隨機索引,然后再排序并返回。
有幾個方法可以讓它快起來。
基本思想就是先獲取一個隨機數,然后使用這個隨機數來獲取指定的行。
由于所有的行都有一個唯一的id,我們將只取最小和最大id之間的隨機數,然后獲取id為這個數行。為了讓這個方法當id不連續時也能有效,我們在最終的查詢里使用”>=”代替”=”。
為了獲取整張表的最小和最大id,我們使用MAX()和MIN()兩個聚合函數。這兩個方法會返回指定組里的最大和最小值。在這里這個組就是我們表里的所有id字段值。
方案二:
復制代碼 代碼如下: <?php
$range_result = mysql_query( " SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM `table` ");
$range_row = mysql_fetch_object( $range_result );
$random = mt_rand( $range_row->min_id , $range_row->max_id );
$result = mysql_query( " SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
就像我們剛才提到的,這個方法會用唯一的id值限制表的每一行。那么,如果不是這樣情況怎么辦?
下面這個方案是使用了MySQL的LIMIT子句。LIMIT接收兩個參數值。第一個參數指定了返回結果第一行的偏移量,第二個參數指定了返回結果的最大行數。偏移量指定第一行是0而不是1。
為 了計算第一行的偏移量,我們使用MySQL的RAND()方法從0到1之間生成一個隨機數。然后我們把這個數字跟我們用COUNT()方法獲取倒的表記錄 數相乘。由于LIMIT的參數必須是int型而不能是float,我們使用FLOOR()來處理結果。FLOOR()會計算小于表達式的最大值。最終的代 碼就是這樣:
方案三:
復制代碼 代碼如下: <?php
$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `table` LIMIT $offset, 1 " );
在MySQL 4.1以后我們可以使用子子查詢合并上面兩個方法:
方案四:
復制代碼 代碼如下: SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;
這個方案跟方案二有同樣的弱點,只對有唯一id值的表有效。
記住我們最初尋找選擇隨機行的替代方法的原因,速度!所以,這些方案的在執行時間上的比較會怎么樣?我不會指出硬件和軟件配置或者給出具體的數字。大概的結果是這樣的:
最慢的是解決方案一(我們假定它用了100%的時間)。
方案二用了79%
方案三 – 13%
方案四 – 16%
so, 方案三勝出!
轉載于:https://www.cnblogs.com/try-better-tomorrow/p/5221481.html
總結
以上是生活随笔為你收集整理的MySQL查询随机数据的4种方法和性能对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求你是医治的神歌词。
- 下一篇: 求一个男孩子姓王好听的名字!