從資料表中隨機抽取資料是常見需求。MySQL 提供了簡單的 ORDER BY RAND() 語法,但在大量資料下效能較差。本文比較兩種寫法的效能差異,並說明適用版本限制。
SELECT * FROM table_name ORDER BY RAND() LIMIT 5;
原理: MySQL 會為每一行產生隨機數並排序,資料量大時極其耗費資源。
官方文件說明: RAND() 回傳 0~1 間的浮點數;若指定種子 RAND(N),則產生固定序列。在 ORDER BY 中使用會重複計算,MySQL 3.23 後支援此用法。
實測: 8,000 筆資料需 0.08 秒。
SELECT *
FROM table_name AS r1
JOIN (
SELECT ROUND(RAND() * (SELECT MAX(id) FROM table_name)) AS id
) AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 5;
原理: 先取得最大 ID,乘以隨機數產生隨機起始點,再以索引快速定位後續資料,避免全表排序。
實測: 同樣 8,000 筆資料僅需 0.02 秒,效能提升 4 倍。
限制: 僅支援 MySQL 4.1 以上版本(需支援子查詢)。
RAND():回傳 0~1 隨機浮點數。RAND(N):以 N 為種子,產生可重複的隨機序列。WHERE 子句中使用 RAND() 會在每次執行時重新計算,不宜用於索引查詢條件。| 情境 | 建議寫法 |
|---|---|
| 資料量 < 1 萬筆 / MySQL 版本舊 | ORDER BY RAND() LIMIT N |
| 資料量大 / MySQL 4.1+ / 有主鍵 ID | 子查詢 JOIN 寫法 |
| 極大資料量 (百萬以上) | 應用層先取得總數,隨機產生 OFFSET,再 LIMIT 1 多次查詢 |