SELECT * FROM table_name ORDER BY RAND() LIMIT 5;
官方文檔明確警告:ORDER BY 子句中使用 RAND() 會導致該列被多次計算,全表掃描+臨時表+文件排序,15 萬行表查 5 行耗時 8 秒+。
id 的連續性(或近似連續)id 閾值JOIN 快速定位到該行及其後 N 行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 ON t1.id >= t2.id
ORDER BY t1.id ASC
LIMIT 5;
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;
| 方案 | 單次耗時 | 10 次總耗時 | 備註 |
|---|---|---|---|
| ORDER BY RAND() | ~8 秒 | ~80 秒 | 全表掃描+臨時表+filesort |
| WHERE id >= (子查詢) | ~0.5 秒 | ~5 秒 | 子查詢執行多次 |
| JOIN 子查詢(推薦) | ~0.01 秒 | ~0.015 秒 | 索引範圍掃描,極快 |
SELECT id FROM table ORDER BY RAND() LIMIT 1 取隨機 ID,再回表查詳情LIMIT offset, 1