V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
soho176
V2EX  ›  MySQL

mysql 如何高效的 随机取数据?

  •  
  •   soho176 · 2013-03-24 19:40:00 +08:00 · 5621 次点击
    这是一个创建于 4256 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我想从文章列表里面随机取出固定数量的文章列表,现在的文章数量是200万,如何执行sql会高效/
    不想用order by rand。
    mysql对随机查询处理能力很差,遇到order by rand,就要全表扫描,性能非常差,容易给cpu耗死。
    13 条回复    1970-01-01 08:00:00 +08:00
    lusin
        1
    lusin  
       2013-03-24 19:42:20 +08:00   ❤️ 1
    先随机取0-200w的一些数字,再按ID取数据会不会快?
    tysx
        2
    tysx  
       2013-03-24 21:21:30 +08:00
    如果ID是连续的就随即取几个范围内的数字,然后select in
    rqrq
        3
    rqrq  
       2013-03-24 22:25:24 +08:00
    网上遍地都是解决办法,有试过么?

    SELECT * FROM tbl AS t1
    INNER JOIN (
    SELECT ROUND(RAND() * ((
    SELECT MAX(id) FROM tbl
    ) - (
    SELECT MIN(id) FROM tbl
    )) + (
    SELECT MIN(id) FROM tbl
    )) AS id) AS t2
    WHERE t1.id >= t2.id ORDER BY t1.id
    LIMIT 1
    soho176
        4
    soho176  
    OP
       2013-03-25 14:18:50 +08:00
    id不是连续的,如果一个一个的取的话,那取的次数太多了,比如取10个随机文章就要查询数据库10次,效率有点低吧
    dementrock
        5
    dementrock  
       2013-03-25 14:46:58 +08:00
    dementrock
        6
    dementrock  
       2013-03-25 14:48:29 +08:00
    或者给每个post都assign一个连续的fake_id?时间长了如果post有删除的话可以定期更新这些fake_id 反正不会有其它用途
    min
        7
    min  
       2013-03-25 16:06:32 +08:00
    效率低不怕,预先半夜跑好几百份随机列表,要用的时候几百份里面取一份呗
    kisa77
        8
    kisa77  
       2013-03-25 17:47:49 +08:00   ❤️ 1
    分享一个以前用过的,1楼的方法如果主键非连续数字就不好使了

    select SQL_NO_CACHE cid,account,country,companyname

    FROM f_company as c

    JOIN (select ROUND(rand() * ((SELECT MAX( cid )

    FROM f_company))) as id) AS T

    where c.cid >= T.id limit 10

    当时是80万记录的f_company表(约780M)用时在0.006秒到0.016秒之间,可以接受
    soho176
        9
    soho176  
    OP
       2013-03-25 18:08:51 +08:00
    @min 几百份太少了,想让每个文章页面都放上随机文章10篇。
    soho176
        10
    soho176  
    OP
       2013-03-25 18:23:10 +08:00
    @rqrq 试过了几个都不理想,你的这个我刚试了 效率也低,随机取了10条,都用了0.05秒。
    soho176
        11
    soho176  
    OP
       2013-03-25 18:35:59 +08:00
    @kisa77 试了一下和2楼@rqrq 的效率差不多。
    risent
        12
    risent  
       2013-03-26 15:38:15 +08:00
    楼主这种每个页面都要显示随机数据的话,数据库处理起来估计很难高效,可以尝试下Solr里面的RandomSortField。
    napoleonu
        13
    napoleonu  
       2013-03-27 13:55:03 +08:00
    你有自增主键ID么?如果有的话:

    1.假设你每次需要随机50篇文章。
    2.让程序随机出100个不重复ID,之所以是100个是防止某些文章删除了,可根据情况调整。
    3.用select * from post where id in (2,3,5,7,11...) limit 50;取出文章。
    4.好了。即使你运气比较差,随机的100个ID里面有60篇文章被删除了,那就随他去吧,who care?

    如果没有自增ID,那么就调整业务加一个,不管是针对业务需求还是数据库性能优化都有好处,之后再使用上面的方案。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5898 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:36 · PVG 11:36 · LAX 19:36 · JFK 22:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.