萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 隨機抽取 N 筆資料:ORDER BY RAND() 與高效替代方案

最直覺的 ORDER BY RAND() LIMIT N 在大表極慢(全表排序)。本文提供基礎寫法、兩種高效子查詢方案並附實測效能對比。

基礎寫法(小表適用)

SELECT `title`, `id` FROM news ORDER BY RAND() LIMIT 0, 5;

資料 < 2,000 筆可接受;超過會明顯拖慢。

高效方案一:JOIN 子查詢(推薦)

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 次平均 0.015 秒。

高效方案二:WHERE 子查詢

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 秒,慢近 10 倍。

原理說明

  1. 先算出 ID 範圍 [MIN, MAX]
  2. 隨機取一個起始 ID
  3. 利用索引 WHERE id >= 隨機值 ORDER BY id LIMIT N 直接定位,避免全表排序

適用條件與限制

  • 表需有連續或近似連續的自增主鍵
  • 大量刪除導致 ID 稀疏時會偏向存活 ID 密集區
  • 嚴格均勻隨機需求時,仍需 ORDER BY RAND() 或應用層抽樣

結論:百萬級以上表強烈建議用 JOIN 子查詢方案;小表直用 RAND() 即可。

copyright © 萬盛學電腦網 all rights reserved