| 方案 | 核心思路 | 相对耗时 | 适用条件 |
|---|---|---|---|
1. ORDER BY RAND() | 建临时表+随机排序 | 100% (基准) | 小表、一次性脚本 |
| 2. MAX/MIN ID + 随机数 | 应用层生成随机 ID,WHERE id >= rand LIMIT 1 | 79% | 主键连续或稀疏可接受 |
3. RAND() * COUNT(*) 计算偏移 | 单次查询得偏移,LIMIT offset,1 | 13% (最快) | 任意表结构,无需连续 ID |
| 4. 子查询融合方案 3 | WHERE id >= (SELECT FLOOR(MAX(id)*RAND()) ...) | 16% | 需唯一主键,纯 SQL 完成 |
SELECT * FROM `table` ORDER BY RAND() LIMIT 1;
全表物化、排序、临时表,百万行级直接拖垮库。
$range = mysql_query("SELECT MAX(id) max_id, MIN(id) min_id FROM `table`");
$row = mysql_fetch_object($range);
$random = mt_rand($row->min_id, $row->max_id);
$result = mysql_query("SELECT * FROM `table` WHERE id >= $random LIMIT 1");
优点:只查两次,无临时表。缺点:ID 稀疏时概率偏向大 ID 端;需两次往返。
$offset = mysql_query("SELECT FLOOR(RAND() * COUNT(*)) AS offset FROM `table`");
$row = mysql_fetch_object($offset);
$result = mysql_query("SELECT * FROM `table` LIMIT {$row->offset}, 1");
SELECT * FROM `table`
WHERE id >= (SELECT FLOOR(MAX(id) * RAND()) FROM `table`)
ORDER BY id LIMIT 1;
单次网络往返,但需唯一主键且分布相对均匀。
-- 方案 3 扩展
SELECT * FROM `table`
WHERE id IN (
SELECT DISTINCT FLOOR(RAND() * (SELECT MAX(id) FROM `table`))
FROM `table` LIMIT 10 -- 产生 10 个随机偏移
)
LIMIT 10;
或应用层生成 N 个不重复偏移,拼 IN (...)。