最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql中RAND()隨便查詢(xún)記錄效率問(wèn)題和解決辦法分享

 更新時(shí)間:2012年04月19日 00:57:22   作者:  
在我們做開(kāi)發(fā)的中效率一直是個(gè)問(wèn)題,特別是對(duì)于很多大數(shù)據(jù)量操作,今天我們碰到一個(gè)要隨機(jī)查詢(xún)數(shù)據(jù),一開(kāi)始我們可能想到最簡(jiǎn)單的order by rand() 來(lái)操作但效率不敢恭維啊
最近由于需要大概研究了一下MYSQL的隨機(jī)抽取實(shí)現(xiàn)方法。舉個(gè)例子,要從tablename表中隨機(jī)提取一條記錄,大家一般的寫(xiě)法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。
有兩個(gè)方法可以達(dá)成以上效果.
1.新建一個(gè)表,里面存著 -5 至 5 之間的數(shù).再利用order by rand()得到隨機(jī)數(shù).
#建立指定范圍數(shù)據(jù)表
復(fù)制代碼 代碼如下:

#auther: 小強(qiáng)(占卜師)
#date: 2008-03-31
create table randnumber
select -1 as number
union
select -2
union
select -3
union
select -4
union
select -5
union
select 0
union
select 1
union
select 2
union
select 3
union
select 4
union
select 5

#得到隨機(jī)數(shù)
#auther: 小強(qiáng)(占卜師)
#date: 2008-03-31
select number
from randnumber order by rand() limit 1

優(yōu)點(diǎn): 隨機(jī)數(shù)可以指定某部分?jǐn)?shù)據(jù),并不需要連續(xù)的.
缺點(diǎn): 當(dāng)隨機(jī)數(shù)范圍很廣的時(shí)候,建表比較困難.
2.利用MySQL的ROUND()加上RAND()函數(shù)實(shí)現(xiàn)
#一句sql語(yǔ)句搞定
#auther: 小強(qiáng)(占卜師)
#date: 2008-03-31
復(fù)制代碼 代碼如下:

SELECT ROUND((0.5-RAND())*2*5)
#注釋
#0.5-rand()可以得到-0.5 至 +0.5的隨機(jī)數(shù)
#(0.5-rand())*2可以得到-1 至 +1的隨機(jī)數(shù)
#(0.5-rand())*2*5可以得到-5 至 +5的隨機(jī)數(shù)
#ROUND((0.5-RAND())*2*5)可以得到-5 至 +5的隨機(jī)整數(shù)

但是,后來(lái)我查了一下MYSQL的官方手冊(cè),里面針對(duì)RAND()的提示大概意思就是,在ORDER BY從句里面不能使用RAND()函數(shù),因?yàn)檫@樣會(huì)導(dǎo)致數(shù)據(jù)列被多次掃描。但是在MYSQL 3.23版本中,仍然可以通過(guò)ORDER BY RAND()來(lái)實(shí)現(xiàn)隨機(jī)。
但是真正測(cè)試一下才發(fā)現(xiàn)這樣效率非常低。一個(gè)15萬(wàn)余條的庫(kù),查詢(xún)5條數(shù)據(jù),居然要8秒以上。查看官方手冊(cè),也說(shuō)rand()放在ORDER BY 子句中會(huì)被執(zhí)行多次,自然效率及很低。

搜索Google,網(wǎng)上基本上都是查詢(xún)max(id) * rand()來(lái)隨機(jī)獲取數(shù)據(jù)。
復(fù)制代碼 代碼如下:

SELECT * FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2 WHERE t1.id >= t2.id ORDER BY t1.id ASC LIMIT 5;

但是這樣會(huì)產(chǎn)生連續(xù)的5條記錄。解決辦法只能是每次查詢(xún)一條,查詢(xún)5次。即便如此也值得,因?yàn)?5萬(wàn)條的表,查詢(xún)只需要0.01秒不到。
下面的語(yǔ)句采用的是JOIN,mysql的論壇上有人使用
復(fù)制代碼 代碼如下:

SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;

我測(cè)試了一下,需要0.5秒,速度也不錯(cuò),但是跟上面的語(yǔ)句還是有很大差距??傆X(jué)有什么地方不正常。
于是我把語(yǔ)句改寫(xiě)了一下。
復(fù)制代碼 代碼如下:

SELECT * FROM `table`
WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))
ORDER BY id LIMIT 1;

這下,效率又提高了,查詢(xún)時(shí)間只有0.01秒
最后,再把語(yǔ)句完善一下,加上MIN(id)的判斷。我在最開(kāi)始測(cè)試的時(shí)候,就是因?yàn)闆](méi)有加上MIN(id)的判斷,結(jié)果有一半的時(shí)間總是查詢(xún)到表中的前面幾行。
完整查詢(xún)語(yǔ)句是:
復(fù)制代碼 代碼如下:

SELECT * FROM `table`
WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`)))
ORDER BY id LIMIT 1;
SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id LIMIT 1;

最后在php中對(duì)這兩個(gè)語(yǔ)句進(jìn)行分別查詢(xún)10次,
前者花費(fèi)時(shí)間 0.147433 秒
后者花費(fèi)時(shí)間 0.015130 秒
看來(lái)采用JOIN的語(yǔ)法比直接在WHERE中使用函數(shù)效率還要高很多。
經(jīng)過(guò)多次測(cè)試我們得出的結(jié)果是利用join的語(yǔ)法比在where中的直接使用要快速不少啊,有更好提交的朋友可以出來(lái)討人聊聊。

相關(guān)文章

最新評(píng)論

和政县| 新兴县| 富蕴县| 惠来县| 长宁区| 民权县| 泽库县| 霍城县| 固安县| 龙游县| 黄陵县| 子长县| 玉门市| 平山县| 二连浩特市| 涟水县| 淄博市| 黄梅县| 井冈山市| 修武县| 鹤壁市| 荥阳市| 文昌市| 昭平县| 仙桃市| 大丰市| 油尖旺区| 湄潭县| 蓬莱市| 运城市| 会理县| 建宁县| 长子县| 遵义市| 兴化市| 秦安县| 兴海县| 嘉兴市| 镇坪县| 磐石市| 龙山县|