mysql> select rand();
+-------------------+
| rand() |
+-------------------+
| 0.048264377795406 |
+-------------------+
1 row in set (0.00 sec)
mysql> select rand();
+-------------------+
| rand() |
+-------------------+
| 0.557701361885016 |
+-------------------+
1 row in set (0.00 sec)
mysql> select rand();
+-------------------+
| rand() |
+-------------------+
| 0.643713706772508 |
+-------------------+
1 row in set (0.00 sec)
mysql> select rand();
+-------------------+
| rand() |
+-------------------+
| 0.545464478941136 |
+-------------------+
1 row in set (0.00 sec)
rand() 函式返回的是乙個小於1的隨機數
但是,後來我查了一下mysql的官方手冊,裡面針對rand()的提示大概意思就是,在order by從句裡面不能使用rand()函式,因為這樣會導致資料列被多次掃瞄。但是在mysql 3.23版本中,仍然可以通過order by rand()來實現隨機。
但是真正測試一下才發現這樣效率非常低。乙個15萬餘條的庫,查詢5條資料,居然要8秒以上。檢視官方手冊,也說rand()放在order by 子句中會被執行多次,自然效率及很低。
you cannot use a column with rand() values in an order by clause, because order by would evaluate the column multiple times.
搜尋google,網上基本上都是查詢max(id) * rand()來隨機獲取資料。
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;
但是這樣會產生連續的5條記錄。解決辦法只能是每次查詢一條,查詢5次。即便如此也值得,因為15萬條的表,查詢只需要0.01秒不到。
下面的語句採用的是join,mysql的論壇上有人使用
select *
from `table`
where id >= (select floor( max(id) * rand()) from `table` )
order by id limit 1;
我測試了一下,需要0.5秒,速度也不錯,但是跟上面的語句還是有很大差距。總覺有什麼地方不正常。
於是我把語句改寫了一下。
select * from `table`
where id >= (select floor(rand() * (select max(id) from `table`)))
order by id limit 1;
這下,效率又提高了,查詢時間只有0.01秒
最後,再把語句完善一下,加上min(id)的判斷。我在最開始測試的時候,就是因為沒有加上min(id)的判斷,結果有一半的時間總是查詢到表中的前面幾行。
完整查詢語句是:
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中對這兩個語句進行分別查詢10次,
前者花費時間 0.147433 秒
後者花費時間 0.015130 秒
看來採用join的語法比直接在where中使用函式效率還要高很多。
最近在學習python+flask+vue.js 搭建乙個前後臺專案
裡面有個需求就是從資料表中隨機取一條資料
最原始最直觀的語法,如下:
select * from foo order by rand() limit 1
當資料表中資料量較小時,此方法可行。但當資料量到達一定程度,比如100萬資料或以上,就有很大的效能問題。如果你通過explain來分析這個 語句,會發現雖然mysql通過建立一張臨時表來排序,但由於order by和limit本身的特性,在排序未完成之前,我們還是無法通過limit來獲取需要的記錄。亦即,你的記錄有多少條,就必須首先對這些資料進行排序。
官方:you cannot use a column with rand() values in an order by clause, because order by would evaluate the column multiple times.
還有很多其他的方法基本都有些效能問題
直接上sql語句,就是它
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;
mysql 隨機選擇一條記錄
mysql 快速隨機選取一條記錄的思考 2010年07月14日 星期三 10 43 標籤 mysql 隨機 分類 mysql 2010 03 04 12 23 本文討論的是如何從mysql乙個資料表中提取一條隨機的效率,同時要保證效率最高。方法一 這是最原始最直觀的語法,如下 select from...
MySQL查月底最後一條記錄
人工智慧,零基礎入門!第一種方法 選定時間範圍,然後倒序排序,通過limit關鍵字只查第1行就是最後一條記錄 select from order where order time 2019 10 01 and order time 2019 11 01 order by order time des...
從mysql中查最後一條記錄
select from table order by id desc limit 1 mysql select from 表名 or der by 表 id desc limit 1 sqlserver oracle select top 1 from 表名 order by 表 id desc 首...