缓存遇到的数据过滤与分页问题

遇到的问题

一、最初阶段

系统中作了一个监控功能,用于记录全部的请求数据,数据插入频繁,量很是大,好比一天1000万条。考虑到数据插入的效率,就使用内存KV缓存来保存。写入过程是在接收到请求后放入到线程池中,而后线程池异步处理后写入。到这问题基本上没什么事情。mysql

二、新的需求

后面数据保存了,就须要在运维系统中能够查询到,因此这个缓存还必须是分布式的。因而就换成了redis,这样系统均可以链接到。可是数据量太大,须要分页查询,这就有点头痛了。还好redis是能够支持有序集合的,并且能够经过zrange来获取指定范围数据。redis

三、增长了需求

这些数据要在运维界面里还要能够按条件过滤,这个就很是头疼啦,redis没有条件过滤啊。即便过滤出来了数据要显示在界面上必须分页。sql

问题思考

最终忽然发现若是存在数据库里是否是很好解决?可是存在数据库里就会有大量写操做的问题,并且数据这么大,像Mysql单表很容易就破了。因此我想着是否是仍是在nosql的基础上解决。数据库

这里就有几个问题:大数据量的排序、查找过滤、分页。缓存

先无论这么多,若是使用Mysql的话,除了大表保存问题,查找、过滤、分页功能都是直接使用sql实现的,开发起来简单。运维

mysql

若是使用mysql存储后,若是要查一些数据怎么整?先看下面的这段代码:异步

SELECT t.* 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

这里最直接的就体现了两点:先排序,而后取分页的数据。好了,这里有几个问题:nosql

一、使用了*返回字段,全字段返回的问题就是要扫描全表
二、进行了ORDERBY排序,我测试的这个表只有几百万数据
三、最后分页是取的130万开始的100条,等因而要扫描130万后才开始分布式

我随便跑了一下执行了:5.5秒左右。有没有办法让它快一点呢?确实有,网上找找挺多的。性能

首先,看看只返回部分字段是否是快一些?

SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

上面的SQL语句,改造后,只返回一个字段,再执行。2.9秒了。

那么取1条数据的速度会不会快一些呢?

SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1

执行上面的sql后发现时间仍是2.9秒,这说明取1条的数据也是这么慢,那慢的确定就是排序啦。

而后使用这一条取出来的数据做为条件,直接在集合中定位到分页数据

SELECT ofOffline1.* FROM ofOffline1 WHERE ofOffline1.creationDate <(
SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1
) 
ORDER BY ofOffline1.creationDate desc
LIMIT 100

这是网上查到的SQL,思路就是先使用子查询定位到第130万条记录,而后从它开始取后面的99条。时间差很少3.9秒左右。这说明这样的优化仍是有效的。

使用一下索引
我想了想若是加个索引是否是能够提高性能呢?SQL中只使用了creationDate排序和过滤,那么就用它建个索引试试吧。

仍是测试一下最简单的那条SQL

SELECT t.* 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

结果是:5.5秒左右,没变化

那么看看前面有子查询的状况:

SELECT ofOffline1.* FROM ofOffline1 WHERE ofOffline1.creationDate <(
SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1
) 
ORDER BY ofOffline1.creationDate desc
LIMIT 100

不错,执行结果:0.599秒。

好吧,本文先到这,后面再学习一下mangodb,按理它会比较适合咱们的场景。

相关文章
相关标签/搜索