怎么评价 order by rand() limit 1 这条 sql - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liu3734
V2EX    数据库

怎么评价 order by rand() limit 1 这条 sql

  •  
  •   liu3734 3 天前 1782 次点击
    14 条回复    2025-10-18 15:37:00 +08:00
    GoogleQi
        1
    GoogleQi  
       3 天前
    数据多,性能差
    w568w
        2
    w568w  
       3 天前
    说明这人知识没更新过,不知道早在 SQL 2003 就已经有 TABLESAMPLE 子句了

    SQL Server:
    SELECT * FROM items TABLESAMPLE (1 ROWS);
    JiaZombie
        3
    JiaZombie  
       3 天前
    SQL 语句分析:ORDER BY RAND() LIMIT 1
    优点
    随机性: 使用 ORDER BY RAND() 可以从结果集中随机选出一条记录,非常适合需要随机抽样的场景。
    简单易用: 语法简单,易于理解和应用,直接满足随机取数的需求。
    缺点
    缺点 描述
    性能问题 当数据表非常大时,ORDER BY RAND() 可能会导致全表扫描,从而影响性能。
    不适合高频请求 在高频请求中,使用这种方法可能会导致数据库性能下降,尤其是在并发量大的情况下。
    可扩展性差 随着数据量的增长,这种方法的效率将显著降低,不适合用于大规模应用。
    更优替代方案
    使用随机数列: 在某些情况下,可以考虑在表中添加一个随机数列,然后通过随机数值来进行选择,具体操作示例如下:
    `SELECT * FROM your_table WHERE random_value >= RAND() ORDER BY random_value LIMIT 1;`
    使用其他随机选取方法: 例如,可以先通过 SELECT COUNT(*) 获取总行数,再利用随机数选择特定行。
    这种方式在性能上通常要优于 ORDER BY RAND(),尤其是表数据量大的情况下。

    总结
    总的来说,ORDER BY RAND() LIMIT 1 是一种简单有效的随机选取方法,但在应用于大量数据时应谨慎使用,需考虑其性能和可扩展性。针对具体应用场景,选择合适的随机选取方法是更好的实践。
    netnr
        4
    netnr  
       3 天前
    类似 C# EF 的 db.Users.ToList().Count
    Rickkkkkkk
        5
    Rickkkkkkk  
       3 天前   1
    @Livid 3 楼 ai
    Gilfoyle26
        6
    Gilfoyle26  
       3 天前
    好奇什么样的业务需要写这样的 sql
    GeruzoniAnsasu
        7
    GeruzoniAnsasu  
       3 天前
    有种前端分页的美
    zhengfan2016
        8
    zhengfan2016  
       3 天前
    @Gilfoyle26 背单词 app 从没背诵的单词行里随机抽一个,音乐 app 随机播放
    Ketteiron
        9
    Ketteiron  
       3 天前
    @Gilfoyle26 #6 获取一条随机数据是很正常的需求,例如随机点一首歌,随机找一位幸运观众 (假设不想使用任何手段的缓存)。

    ------
    其实 rand() 的 O(n*log(n)) 开销在部分场景还是能承受的
    换聚簇索引或者抽样可以快一点:
    https://stackoverflow.com/questions/40273291/sql-select-a-random-row-in-o1-time
    https://stackoverflow.com/questions/60019318/sql-command-to-include-a-random-row-from-the-table
    如果 ID 连续还可以通过两次请求实现 O(1), 但额外请求开销值不值就另说了。
    newtype0092
        10
    newtype0092  
       3 天前
    @Ketteiron 现在真有这么干的么? 数据库资源这么宝贵,用来搞这种无关紧要的边角料业务逻辑有点浪费吧。。。
    moult
        11
    moult  
       3 天前
    看具体业务,比如 where 筛选后数据量很少很少的,用这个方式随机取一条还是方便高效的。
    Ketteiron
        12
    Ketteiron  
       3 天前
    @newtype0092 #10 `随机获得一条数据`这种需求,一般量级也就几千到一两万,调用频率不高就别管了。
    拿 mysql8 试了下,2w 条是 20 毫秒,如果用
    JOIN ( SELECT CEIL(RAND() * (SELECT MAX(id) FROM `xxx`)) AS rand_id )
    替代 rand() 可以快 20%左右
    不超过 5w 我是无所谓,这种奇葩需求一般也不会有大量数据。
    Livid
        13
    Livid  
    MOD
    PRO
       3 天前
    @Rickkkkkkk 谢谢,3 楼的账号已经被彻底 ban 。
    ethusdt
        14
    ethusdt  
       2 天前 via iPhone
    @zhengfan2016 这俩需求都可以让前端做吧,数据库尽量少做随机。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     6064 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 02:01 PVG 10:01 LAX 19:01 JFK 22:01
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86