使用MySQL从20万条数据中通过筛选随机取出1条数据的方法

因为业务需要,要求在一个where筛选完的数据集中随机取出1条数据。

经典的方法

SELECT * FROM table where 条件 ORDER BY RAND() limit 1;

适用入门级应用,怎么这样说呢?

因为数据量小时,倒没多大问题,由于会进行全表扫描,当数据量渐渐巨型时,查询时间会相当变态。

本地环境运行需时在0.276s左右。

百度出来别人验证过,性能高效的方法是

SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id LIMIT 1;

加上我们需要的条件

SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id and 条件1 and 条件2 and 条件3
ORDER BY t1.id LIMIT 1;

我们下面就来测试一下
生产虚拟数据
先生成20万条虚拟数据,要随机生成,保证数据的均匀分布。

跑一下
平均只用0.006s左右

统计符合条件的数目

SELECT COUNT(*) FROM `table` WHERE 条件1 and 条件2 and 条件3;

符合条件的数据有8340条,占比0.0417。

数据校验
运行8000次
校验通过:0.999875, 检验不通过:0.000125
计算了一下,是1条。

运行了两次程序,结果依旧,原因暂未查明。

数据重复性测试

运行出现1次2次3次4次5次6次7次8次9次10次11次12次13次14次
10000.79700.17600.027000000000000
20000.63550.2650.08250.0140.0025000000000
30000.53670.28530.12900.03070.01000.008000000000
40000.46030.29000.13880.05900.03130.01500.00350.0020000000
50000.38440.30000.16320.08720.0420.01320.00840.0016000000
60000.34050.28330.19650.09670.05000.01600.00700.00670.003000000
70000.29900.27000.17010.10000.07290.04970.02300.00690.00390.00430000
80000.2660.25930.19350.10950.07190.04650.02630.0140.00340.00250.00280.004500

由此来看,随机性还是挺不错的,多数数据是出现在前段,这个方法可以使用。

注意:在max,min里面的语句不能再加入where,加入后发现查询明显减慢,经EXPLAIN分析是会导致一条或多条select_type为SUBQUERY进行全表扫描。

原文链接

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lcwai

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值