SELECT * FROM table_name ORDER BY RAND() LIMIT 5;
問題:MySQL 需為每行生成隨機數、排序全表、再取前 N 行。百萬級資料會產生臨時表、檔案排序,耗時秒級甚至分鐘級。
SELECT * FROM `table`
WHERE id >= (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM `table`)))
ORDER BY id LIMIT 1;
缺點:ID 不連續(刪除導致空洞)時,分布不均;且需掃描從隨機點到末尾的所有行。
SELECT * FROM `table` AS t1
JOIN (
SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id
) AS t2 ON t1.id >= t2.id
ORDER BY t1.id LIMIT 5;
缺點:返回連續 5 行,非真正隨機;需執行 5 次取 1 行才均勻。
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 ON t1.id >= t2.id
ORDER BY t1.id LIMIT 1;
| 查詢方式 | 執行 10 次總耗時 | 平均單次 |
|---|---|---|
| ORDER BY RAND() LIMIT 1 | ~5 秒 | 500 ms |
| WHERE id >= (SELECT FLOOR(MAX*RAND())) LIMIT 1 | ~5 秒 | 500 ms |
| 完美隨機子查詢版 | 1.47 秒 | 147 ms |
| JOIN 版完美隨機 | 0.15 秒 | 15 ms |
N 次(應用層循環),收集唯一 ID 集合SELECT id FROM table ORDER BY RAND() LIMIT N 只取 ID(較輕),再 WHERE id IN (...) 回表ORDER BY RAND() 觸發全表掃描 + 檔案排序 → O(N log N)OPTIMIZE TABLE 或重建索引)sample_ids 映射表