Rumah > Artikel > pembangunan bahagian belakang > 文章表500万条数据,每天会有10万条数据更新,从更新的10万条中随机选3000条做数据研究,如果做到高效?
题目是一道面试题
我的想法是另起一张表,存放今天更新的10万条都有哪些;
我只想到这个第一步,接下来该怎么做我还不知道怎么去实现;
假设按我这样的思路,我就算知道了每天更新的是哪10万条数据,那我还是得去500万条中找出3000条数据哦
不知道各位兄弟,有啥好的想法呢?
题目是一道面试题
我的想法是另起一张表,存放今天更新的10万条都有哪些;
我只想到这个第一步,接下来该怎么做我还不知道怎么去实现;
假设按我这样的思路,我就算知道了每天更新的是哪10万条数据,那我还是得去500万条中找出3000条数据哦
不知道各位兄弟,有啥好的想法呢?
10W中的3000条,概率是3%
那么只要在保存文章时,按照3%的概率,把本次更新文章保存到缓存中
这种缓存用redis的set类型最好,set类型不会保存重复的元素,所以文章反复更新也不会在列表里面产生多个结果
key的格式可以用"analyze:list:(Y-m-d)"
然后这个缓存可以设置为48小时过期,如果有需要的话,每天可以拿前一天的缓存归档到数据库
考虑到随机概率的误差,可以把3%放大到5%,最后肯定会记录得超过3000,但是也不会超太多,反正最后只拿3000条来用就行了
把每次更新都记录起来的话,无论是记录到缓存还是数据库,其实大部分的记录是没用的,不如按照概率先过滤一遍
其实记录每条文章的update_time也可以,我觉得where update_time >= ? and update_time
优点:
1、没有update_time字段也能玩,对现有表结构无要求,给生产环境的数据库加字段是件麻烦事
2、万一生产环境的数据库负载比较高,order by random()查询导致数据库卡死也不好,这样的话,最好是读写分离架构,在只读库上查询才行,产生了架构要求,我这个设计完全是个旁路记录,除了redis之外没要求
3、需要多少才记多少,额外IO少
一些粗陋的想法,仅供参考
分区
500万条,为了方便。根据数据的更新时间进行数据库分区(没用过mysql分区的看这个,在文章后面讲了),
比如说按照月份,我假设你这500万条数据是一年的,那么分成12份,每个区大约算42万条记录
这样,当使用更新时间进行搜索的时候,mysql就会根据你的更新时间 去选择分区,
也就是被搜索的数据是在这42万条里面去找(这肯定要比你在500万里面快多了,当然你要是按照天来分,那会更快)
加缓存
这没啥,就是你每天写入mysql的时候取3000条数据写入redis或者mongodb里面,做研究就不从mysql里面读了。用php从缓存里面读
多进程
你说的要做研究嘛,我假设你的研究算法很复杂。你去学学swoole,开三个进程,一个进程处理1000个数据,最后汇总结果
取出当日更新的10万
id放入一个数组在数组中随机取出3000个id
用select in读取指定的3000条记录
<code>SELECT id FROM table WHERE date_refresh = 20120329 SELECT * FROM table WHERE id IN (id_0, id_1, id_2, ..., id_2999) </code>
https://www.zhihu.com/question/20151242
首先,我会使用缓存的方式,将每天更新的数据的主键
记录下来。
从缓存中,随机获取3000
个主键
拿着这3000 个主键,使用 IN 查询,获取对应的数据。
浅陋分析,勿笑。
1.获取id区间
<code>select max(id) as max_id, min(id) as min_id from ( select id from article_tb where update_time >= '2016-02-26 00:00:00' ) </code>
update_time有索引,id为自增长id
2.随机获取
<code>select * from article_tb where id >= min_id and id </code>
查询3000次
<code>// STEP 1 : 获取当天文章ID区间 // maxId -> select max(id) from news where 当天时间限定 // minId -> select min(id) from news where 当天时间限定 // STEP 2 : 取得随机ID // 因为你一天有10万数据,数据总量有很高 // 所以避免使用MYSQL中的随机 $minId = 5000000; $maxId = 5100000; $i = 0; $resultIds = []; while(true){ $randId = rand($minId,$maxId); if(in_array($randId, $resultIds)){ continue; } // 查询验证 // 根据你的需要验证数据是否是审核的呀,是否是正常数据呀 // 如果正常就载入到结果数组中。 $resultIds[] = $randId; $i++; if($i==3000){ break; } } // 到这里结果已经有了 // 可以储存到结果集用其他方式分页进行研究或者浏览。</code>