• 从大表里随机取若干行的效率问题


    知乎里有个问题 在 MySQL 中,从 10 万条主键不连续的数据里随机取 3000 条,如何做到高效? ,用

    select id from t order by rand() limit 3000

    需要花三四十秒,怎么办?

    以下是我的回答:

    慢的原因有两个:

    1)rand()执行了10万次(而不是3000次)

    2)10万条记录进行了排序

    我的方案如下:

    我用informationschema.columns表来举例。这个表在我的数据库里有7482条记录,我要从中取30个column_name。(每个mysql数据库的informationschema.columns记录数不同,用这个表的好处是谁都可以试)

    先看看这张表:

    select count(*) from information_schema.columns;

    mysql> select count(*) from information_schema.columns;
    +----------+
    | count(*) |
    +----------+
    | 7482 |
    +----------+
    1 row in set (0.09 sec)

    第一步是做一个全表查询,加上一个行号字段n,从1到7482 (Mysql没有row_number功能,所以用此法)

    select @x:=@x +1 n,column_name from information_schema.columns,(select @x:=0) x

    结果类似这样:

    | n | column_name |
    | 1 | CHARACTER_SET_NAME |
    | 2 | DEFAULT_COLLATE_NAME |
    | 3 | DESCRIPTION |
    | 4 | MAXLEN |
    | 5 | COLLATION_NAME |

    ……

    其次做一个查询,产生30个随机数,1-7482之间
    select distinct ceil(r*c) n from (select rand() r from information_schema.columns limit 35) t1
    ,(select count(*) c from information_schema.columns) t2
    limit 30

    结果大致是这样的;

    | n
    +------
    | 4452
    | 3838
    | 5835
    | 2694
    | 3449
    | 1678
    |……

    主要子查询t1里故意产生了35个随机数,然后在外面用了distinct,这样可以基本保证有30个不重复的整数

    最后,组装一下做个左连接就可以了:

    select tblrand.n,tbldata.column_name from

    (select distinct ceil(r*c) n from (select rand() r from information_schema.columns limit 35) t1,

     (select count(*) c from information_schema.columns) t2 limit 30) tblrand

    left join

    (select @x:=@x +1 n,column_name from information_schema.columns,(select @x:=0) x) tbldata on tblrand.n=tbldata.n;

     

    总结:

    1)只做了30多次rand(),而不是7400多次。

    2) 没有排序

    3) 对表的ID连续性没要求。实例中的表压根没ID字

    以上例子,用root用户登入mysql就能测试

  • 相关阅读:
    vim对光标所在的数字进行增减
    fedora找开ftpd服务器并以root登陆
    wxwidget自定义消息处理步骤
    c++的检测的确比C++更严格
    php常用字符串操作函数
    如何判断一个数组是一维数组或者是二维数组?用什么函数?
    php 面试 题汇总
    php 数组 常用函数
    php 会话控制
    用tp实现中文验证码
  • 原文地址:https://www.cnblogs.com/yingjiang/p/8540681.html
Copyright © 2020-2023  润新知