SELECT * FROM `table` ORDER BY RAND() LIMIT 1;
**缺點**:MySQL 需為全表產生隨機數、排序、再取前 N 筆,複雜度 O(N log N),百萬筆資料查詢可達秒級,生產環境**嚴禁使用**。
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 ASC LIMIT 5;
**缺點**:取得的是 **連續 5 筆** 而非真正隨機 5 筆;ID 有空洞(刪除導致)時分布不均;需重複執行 5 次才能得到 5 筆不連續資料,效率仍低。
SELECT * FROM `user`
WHERE userId >= (
(SELECT MAX(userId) FROM `user`) - (SELECT MIN(userId) FROM `user`)
) * RAND() + (SELECT MIN(userId) FROM `user`)
LIMIT 5;
**原理**:
[MIN, MAX]。**適用條件**:
UNION ALL 補足)。**適用任意主鍵型別、任意分布、需精確 N 筆不重複**:
-- 階段 1:取得符合條件的主鍵總數 SELECT COUNT(*) INTO @total FROM `table` WHERE ...; -- 階段 2:應用層產生 N 個不重複隨機數 (0 ~ @total-1) -- 假設應用層產生 3, 17, 42 -- 階段 3:資料庫端使用 LIMIT offset, 1 逐筆抓取 SELECT * FROM `table` WHERE ... LIMIT 3, 1; SELECT * FROM `table` WHERE ... LIMIT 17, 1; SELECT * FROM `table` WHERE ... LIMIT 42, 1;
**優化**:將 N 筆 OFFSET 合併為單一查詢(MySQL 8.0+ 支援 LIMIT ... OFFSET ... 陣列語法,或使用 UNION ALL)。
SELECT * FROM `table` TABLESAMPLE SYSTEM (10) LIMIT 100;
SYSTEM:頁面層級抽樣,極快但不精確。BERNOULLI:列層級獨立抽樣,統計特性較好。| 方法 | 時間複雜度 | 隨機度 | 適用場景 |
|---|---|---|---|
| ORDER BY RAND() | O(N log N) | 完美 | 小表(<1萬列)、一次性報表 |
| MAX*RAND JOIN | O(log N + Limit) | 連續區塊 | ID 連續、允許連續區塊 |
| ID 範圍隨機 | O(log N + Limit) | 近似均勻 | 自增整數主鍵、高頻隨機抽取 |
| 兩階段 OFFSET | O(N) 計數 + O(log N) * N | 完美 | 任意主鍵、精確 N 筆、中等資料量 |
| TABLESAMPLE | O(樣本大小) | 統計近似 | 超大表統計分析、近似聚合 |
ORDER BY rand_sort LIMIT N。WHERE id > last_seen_id ORDER BY id LIMIT N 替代 OFFSET,避免深分頁效能崩塌。Rows_examined,確認掃描行數符合預期。