记一次业务开发涉及到的查询优化
前言
老王:最近业务挺多的啊!
小李:对啊,最近这不是要上线了嘛!,业务就开始多了起来!
老王:最近有写到好玩的业务嘛!
小李:都是增删改查,哪有好玩的!
老王:最近不是要你实现查询全服玩家的战力并且每个人都有一份对应战力区间的挑战列表吗?我感觉还挺有意思的,说一下怎么写的呗
小李:哈哈哈我也没用什么好思路,就是异步多线程扫表,下面我讲一下具体实现的吧!
需求
全服玩家的战力并且每个人都有一份对应战力区间的挑战列表,不用实时更新,但需保存当时的玩家状态,每两天重置一遍列表!
分析
小李: 首先全服玩家的战力,这个无法避免会去扫整个表!
老王: 那咱们产品要是火了有上千万数据咋办?查下来的时间都够玩家去打把LoL了
小李: 所以我用异步的形式去扫表,提前先去更新好挑战列表!
老王:嗯这个是可以,但是挑战列表每个玩家都不一样,那全服玩家都要生成一遍不一样的,这比查全服的玩家还可怕啊!
小李: 哈哈这个我也有考虑到,我异步去更新的是一份整个库的战力区间列表,把库里面的所有人战力等级以比如每隔1000战力的形式去缓存Key在redis中,这样不管是哪个玩家要取他自己的战力区间列表时都不会错了,
老王:那每个玩家的挑战区间列表就是从全服的挑战列表缓存里面去随机然后取出来再缓存到自己每个人身上对吧!那的确通过异步缩小了查询范围!
小李:是呀,每隔玩家要取的时候,就固定自己的战力列表就好了,过期时间为刷新的两天要求!
老王:那你扫表还是很普通的扫全表,千万数据的访问速度依然没解决啊!虽然采用了异步,避免了等待,但是我相信你肯定这一步也会去优化的把!
小李:不愧是老王,问题都想到了!其实扫全表,无非就是利用索引,缩小范围,多线程一起扫,加快时间和速度!
小李:首先是索引,因为我们这个战力字段不太适合作为索引,因为是范围查询,不满足最左匹配原则呢!但是我可以用覆盖索引,将我要查询的字段全都覆盖到!这样会快一点!
老王:索引的确看场景。那多线程呢?
小李:同时开启多个线程,然后每个线程都做一件事去采集玩家的战力然后放到合适的桶里,这个过程需要加锁保证数据的一致性!然后最后再统一合并!这个过程我会分页去查询数据库的数据,否则一次查出来的数据太大,和全表查效率一样是慢的,分批加载更适合你要去筛选的数据,且每个线程去做不同页的数据采集!
老王:这个方法放异步里两天执行一次就可以了,哈哈哈可以啊,下次有业务我还交给你!