MySQL 官方文檔明確指出:ORDER BY 子句中使用 RAND() 會導致該列被多次掃描評估。實測 15 萬條數據查 5 條耗時 8 秒+,隨數據量線性惡化。
SELECT t1.*
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 次查詢總耗時 0.015 秒,較 WHERE 子查詢法(0.147 秒)快近 10 倍。
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;
缺點:未加 MIN(id) 判斷時,有 50% 概率只查到前幾行。
SELECT MAX(id), MIN(id) FROM tablerand_id = MIN + floor(RAND() * (MAX - MIN + 1))SELECT * FROM table WHERE id >= rand_id ORDER BY id LIMIT 1需處理 ID 不連續導致的分布不均,可循環重試或結合 COUNT(*) 加權。
LIMIT 1 循環 N 次,總耗時仍遠低於 ORDER BY RAND()TABLESAMPLE SYSTEM (10) 伯努利採樣(近似隨機)採用 JOIN 子查詢方案,配合主鍵索引,即可實現毫秒級隨機查詢,徹底解決大表隨機抽樣效能難題。