欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

文章表500万条数据,每天会有10万条数据更新,从更新的10万条中随机选3000条做数据研究,如果做到高效?

程序员文章站 2022-05-28 09:47:36
...
题目是一道面试题
我的想法是另起一张表,存放今天更新的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个数据,最后汇总结果

  1. 取出当日更新的10万

  2. id放入一个数组在数组中随机取出3000个id

  3. 用select in读取指定的3000条记录

SELECT id FROM table WHERE date_refresh = 20120329

SELECT * FROM table WHERE id IN (id_0, id_1, id_2, ..., id_2999)

https://www.zhihu.com/question/20151242

  • 首先,我会使用缓存的方式,将每天更新的数据的主键 记录下来。

  • 从缓存中,随机获取3000主键

  • 拿着这3000 个主键,使用 IN 查询,获取对应的数据。

浅陋分析,勿笑。

1.获取id区间

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'
) 

update_time有索引,id为自增长id
2.随机获取

select * 
from article_tb 
where id >= min_id and id 

查询3000次

// 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;
    }
}

// 到这里结果已经有了
// 可以储存到结果集用其他方式分页进行研究或者浏览。
相关标签: php mysql