需從大量資料中隨機抽取樣本是常見需求,但 ORDER BY RAND() 在資料量大時效能極差。本文分析原因並提供優化方案。
SELECT * FROM table_name ORDER BY RAND() LIMIT 5;
RAND() 回傳 0~1 浮點數,可帶種子值 RAND(N) 產生可重現序列。適用 MySQL 4.1+ (支援子查詢):
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;
>= 向後取 N 筆,利用索引快速定位| 方法 | 適用版本 | 效能 | 備註 |
|---|---|---|---|
| ORDER BY RAND() | 所有版本 | 差 | 全表掃描排序 |
| MAX(ID) 隨機 + JOIN | 4.1+ | 優 | 需連續主鍵 |
| 應用層產生隨機 ID | 所有版本 | 佳 | 需多次查詢、應用層邏輯 |
| TABLESAMPLE (8.0+) | 8.0+ | 極佳 | 伯努利/系統取樣 |
ORDER BY RAND()TABLESAMPLE SYSTEM (10) 取樣 10% 頁面RAND(),會重複計算