SELECT * FROM `table` ORDER BY RAND() LIMIT 5;
官方文件明確指出:RAND() 在 ORDER BY 中會被執行多次,大表效能極差(15 萬筆資料查 5 筆需 8 秒以上)。
SELECT * FROM `table`
WHERE id >= (SELECT FLOOR(MAX(id) * RAND()) FROM `table`)
ORDER BY id LIMIT 1;
測試約 0.5 秒,但易產生連續 ID,且未處理 MIN(id) 導致前段資料機率過高。
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;
MIN(id) 修正分布偏移。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 次總耗 0.147 秒,慢於 JOIN 版約 10 倍。
UPDATE cdb_posts SET views = RAND();
單陳述式即可為全表賦隨機值,無需迴圈。
ORDER BY RAND()。id 有索引且分布相對連續;若有大量刪除導致空洞,考慮建立連續序列輔助表。