zoukankan      html  css  js  c++  java
  • 从大表里随机取若干行的效率问题

    知乎里有个问题 在 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就能测试

  • 相关阅读:
    Document
    Document
    Document
    2.原型和原型链的关系以及查找顺序
    1.面向对象 及 相关知识点
    时间对象 <-> 定时器 <-> 电子时钟 <-> 倒计时效果
    定时器
    let var const 的区别
    ES6 中块的概念
    js中的闭包
  • 原文地址:https://www.cnblogs.com/yingjiang/p/8540681.html
Copyright © 2011-2022 走看看