Mysql随机所需要考虑的问题

按时间逆序排列,是列表数据的常见排法,不过当用户缺乏活跃,帖子数据增量较少时,就会出现用户几次下拉刷新后,发现没变化,从而认为平台数据太少,没啥好玩的,就离开了。这个时候往往需要考虑做一些随机列表,让用户每次刷新都能看到不一样的内容,延长用户的停留时间。

随机从数据库中取数据,看似简单,实则并不容易,坑很多,要考虑的问题也很多。

最先想到的就是使用如下SQL,一句话搞定:

select * from Subject order by rand() limit 10;

Mysql文档里也有特别描述,使用order by rand()会建立临时表,会全表描述。对于几十万的数据量,奇慢无比,某次愉快的长途旅行,就因为这个SQL,不得不在火车上紧急处理线上问题。

接下来,也很容易想到解决方案,网上的方案也大同小异:

select * from Subject where id >= (select floor(rand() * (max(id) - min(id)) + min(id)) from Subject) limit 1;

不知道为啥,让Mysql自己生成随机数,就会有点慢,所以干脆不用Mysql的rand()函数,而由后端代码生成拼接到SQL中:

select * from Subject where id >= (select floor(0.123 * (max(id) - min(id)) + min(id)) from Subject) limit 1;

注意:这里只能取一条,要取10条,就需要执行10次,所以还不如简化一下,执行11次查询,第一次把min(id)和max(id)查出来,每次由程序算出随机值再拼接入SQL:

select min(id), max(id) from Subject;
select * from Subject where id>=123;
select * from Subject where id>=321;
...

其实这还不够,10条随机数据,有一个隐形条件就是这10条数据自身不能有重复,那么就需要有一个Set进行除重,这样可能会执行11次以上的SQL查询,不过速度还是相当快的。

但也有一个问题,就是当初期,数据量比较少,出现重复数据的概率会非常高,甚至是数据量不足10条时,会导致死循环。所以你需要知道表里大致有多少条数据,比如大于1000条,就按后面的方法走,少于1000条,就直接按order by rand()走,这个判断还是相当快的:

select id from Subject limit 1000,1;

综上,要实现从Mysql数据库表里随机取10条数据,性能佳、逻辑正确,代码量还是不小的。

发表于 2016年11月17日 23:52   评论:0   阅读:1894  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo