SELECT * FROM `table` ORDER BY RAND() LIMIT 1;
原理:為每行生成隨機數 → 臨時表排序 → 取第一行。
複雜度:O(N log N),100 萬行需秒級,1 億行直接掛起。
SELECT * FROM `table`
WHERE id >= (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM `table`)))
ORDER BY id LIMIT 1;
-- 1. 取總行數
SELECT COUNT(*) INTO @total FROM `table`;
-- 2. 計算隨機偏移
SET @offset = FLOOR(RAND() * @total);
-- 3. 取單條
PREPARE stmt FROM 'SELECT * FROM `table` LIMIT ?, 1';
EXECUTE stmt USING @offset;
DEALLOCATE PREPARE stmt;
LIMIT offset, 1(5.6+ 優化過,不再掃描 offset 行)。
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 10;
實測 10 萬行數據 < 0.01 秒,返回 10 條連續記錄(近似隨機塊),適合「隨機推薦」、「隨機抽樣分析」場景。
ALTER TABLE `table` ADD COLUMN `rand_val` DOUBLE NOT NULL DEFAULT 0;
-- 寫入時
INSERT INTO `table` (...) VALUES (..., RAND());
-- 定期更新
UPDATE `table` SET `rand_val` = RAND();
-- 隨機查詢
SELECT * FROM `table` ORDER BY `rand_val` LIMIT 10;
-- 有索引則極快:CREATE INDEX idx_rand ON `table` (`rand_val`);
優勢:讀取 O(log N),寫入微小開銷。適合高頻隨機讀、低頻寫入場景。
| 方案 | 均勻度 | 單次延遲 | 適用場景 | 備註 |
|---|---|---|---|---|
| ORDER BY RAND() | 完美 | O(N log N) 極慢 | < 1 萬行、一次性腳本 | 生產禁用 |
| 主鍵隨機點 + 向後 | 不均勻(受ID分布影響) | 極快(ms) | ID 連續/較密、單條隨機 | 邊界處理 |
| 隨機偏移量 LIMIT | 完美 | 快(兩次查詢) | 需精確均勻、單條/少量 | 5.6+ LIMIT 優化 |
| 主鍵範圍掃描 | 塊級均勻 | 極快 | 批量隨機抽樣、推薦 | 返回連續塊 |
| 預計算 rand_val 列 | 完美 | 極快(索引序) | 高頻隨機讀、可接受寫入開銷 | 需維護列/索引 |
「大表隨機查詢,
ORDER BY RAND()是性能殺手。根據業務容忍度:追求絕對均勻用隨機偏移量,追求極致吞吐用預計算隨機列,允許塊級近似用主鍵範圍掃描。」