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

看到知乎上有人提问

几百万记录的表,每天大概有10万条记录发生更新,从这10万条里随机取3000条做数据分析,

select id from table where date_refresh = 20120329 order by rand() limit 0,3000

这个sql执行起来会很慢,大概三四十秒吧,怎么优化?


这个也算是mysql的一个经典问题了。


上面这种做法是非常不明智的做法,因为RAND()函数的随机因子变成这个表总数据量,所以速度会非常慢,跟读取多少条记录不是特别大的关系;


这个问题解决的基本思路是:

SELECT id FROM table WHERE date_refresh = 20120329
取出当日更新的10万 id (date_refresh 需要建立索引),放内存里面随机 shuffle 一下,顶多占用几 MB 内存,取前 3000 个,然后
SELECT * FROM table WHERE id IN (id_0, id_1, id_2, ..., id_2999)


有个回答特别好, 翻译了国外一个牛人的文章  http://shiningray.cn/order-by-rand.html


主要的思路是,如果id是连续分布,那直接根据max(id)进行获得随机id,然后直接取出

如果id不连续,存在空挡,那么可以总是选择比随机出的id大(或小)的记录

如果id不连续,且必须尽可能平均地获取记录,那么需要额外做一个表,将不连续的id映射成连续id,然后进行随机

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值