问题

我在做论坛的是时候遇到了如下的问题。论坛里可以有很多的主题topic,每个topic对应到很多回复reply。现在要查询某个topic下按照replyTime升序排列的第pageNo页的reply,每页pageSize个reply。

reply是存放在mysql中的。以前的实现是利用mysql的limit查询

由于现在有很多的主题的回复很多,当有人查询第几百甚至几千页的时候,mysql性能表现很不好。“select limit offset, size” 只要offset太大,传统的关系型数据库的性能表现都不好。

如果能够利用带索引的查询条件先过滤掉一部分数据,就可以大大提高性能,比如:

lastReplyIdOfCurrentPage 是当前页的最后一个reply的id。currentPageNo是当前页的页号。这里用replyId过滤条件,把前面页的内容过滤掉,这样减少了 offset的大小。但是当用户需要跳转到很远的一个页面的时候,offset还是会很大。比如,当前是第10页,要跳转到第1000页,offset = 990 * pageSize,还是会很大,性能依旧不行。尽管目前很多产品,都不提供这样的跳转能力了,但是我们的产品团队还是认为这个功能在我们的产品里面不可或 缺。

迁移到cassandra

后来我们把reply数据全部迁移到了cassandra上。cassandra的数据结构和mysql不一样。我们创建了一个topic_reply 列簇,每一行的行号是topicId,每一列是这个topic的replyId,这样得到类似如下结构

1:1,2,5,33,245,663,780...

2:36,78,89,94,235,345...

在cassandra中列是自然排序的,形成了一个从topic到reply的索引。查询的时候只能查询topicId行的列大于(或小于)replyId的size个replyId,相当于sql:

, 不能够 “limit offset, size”。这意味着如果要查询第一千页,而我不知道第一千页开始的replyId是多少,我就得取出这一千页的数据,这显然是行不通的。所以得想办法从靠近我要取的数据的某个replyId处开始取数据。

reids的SortedSet

论是mysql还是cassandra,都不能很好地解决从一个很长的序列中取出任意一段数据的问题,而造成这一问题的根源在于这些数据是存放在磁盘上

的,磁盘不适合做此类的随机读的操作。所以想,如果能有一个程序,管理一些很大很大的放在内存中排序数组就好了,因为对内存中的数组做下标访问,是非常快

速的。做了一下调查正好发现,redis提供了此类的功能。

redis将数据存放到内存中,所以既便是随机读写,速度都是非常快。

redis支持的SortedSet结构正好适合于做分页查询。SortedSet按照给定的score给member排序,允许通过下标或者score

去查询。把同一个topic的replyId作为member,以replyId本身为score存放到SortedSet后,就可以通过下标取值了,例

如:

//存入数据

zadd tr:1 1 1

zadd tr:1 2 2

zadd tr:1 5 5

zadd tr:1 33 33

zadd tr:1 245 245

zadd tr:1 663 663

//pageSize = 3 取 第二页,即下标 3 到5的元素

zrange tr:1 3 5

其中 tr:1 是这个SortedSet的key,”tr:”只是用来区分其它key用的前缀,1是topicId。更详细的内容看redis官网http://redis.io

如此一来,就可以实现任意分页查询了,而且性能非常好。

缓存索引

redis

的数据全部存放到内存中,如果把所有topic到reply的关系都放到内存中,要耗费很多内存,而且这么多的内存实际上很多是浪费的,毕竟大部分的

topic是不活跃的。再者topic到reply的映射关系是非常重要的,所以我们需要把这种关系持久化。最后我们决定,这个映射关系,或者称为索引还

是存放在cassandra里面,只是在需要的时候,才从cassandra里面把索引载入到redis内,然后再利用redis分页查询。如此一

来,redis成了一个支持分页查询的强大的缓存。

分片缓存

对于超长的主题,全新载入到redis一次也是相当的耗时的,我们采取分片来解决这个问题。我们把索引每4800个值分成一片,用另外一个数据结构记录索引长度和索引从第二片开始的每片的开始值。

更新的索引的时候更新这个分片信息,记录各分片的头部是为了便于从cassandra载入分片。

询的时候把分页查询转化成某个片上某段索引的值。当分片大小大于pageSize并且能被pageSize整除时,这个转化是很简单的,因为分页正好会全

部落在某一个分片中。我们之所以把分片大小设置成4800正是因为这个值能被10 15 20 25 30 40 50 60 80 100 200

等很多常用分页大小整除。分片太大浪费内存,分片太小分片就太多。

只要算出这一页所在的分片,然后把需要的索引段载入到redis,再利用redis的分页查询查出结果。这样,只有活跃的索引分段才会被载入到redis内存中。

如果用mysql来持久化索引效果也是类似的,而且查询更加便利能力更强。

总结

只要产品能接受,就不要使用任意分页,任意跳转。确实需要高速分页查询的时候可以使用redis的SortedSet,但是得注意内存大小和持久化问题。

mysql分页 redis_分页查询和redis相关推荐

  1. MySQL中的分页查询

    MySQL中的分页查询 一.MySQL分页查询原则 在MySQL数据库中使用limit子句进行分页查询: MySQL分页中开始位置为0: 分页子句在查询语句的最后侧: 二.Limit子句(较为常 ...

  2. mysql分页limit运算,MySQL的limit分页查询及性能问题

    MySQL 通过 limit 实现分页查询.limit 接收一个或两个整数型参数.如果是两个参数,第一个指定返回记录行的偏移量,第二个指定返回记录行的最大数目.初始记录行的偏移量是 0.为了与 Pos ...

  3. jsp import mysql con_jsp的分页查询的代码(mysql数据库)

    [原来没有写过,听朋友说,比较难,就试一下,还是挺简单的,只不过,具体实用方面还得自己写,没有什么难的,自己看看就懂了.bean文件:package bean;/** * jsp+java bea 这 ...

  4. jq取第一个子元素为select_Java修行第036天---MySQL中的子查询,分页语句,三大范式...

    学习目标: 1.掌握子查询 2.了解正则表达式 3.理解索引的作用和创建索引 4.了解用户管理 5.掌握分页语句 6.了解执行计划和数据库引擎 7.理解数据库设计的三大范式 综合程序图: 1 子查询知 ...

  5. mysql一对多关联查询分页_mysql一对多关联查询分页错误问题的解决方法

    xml问价中查询数据中包含list,需要使用collection .... .... 这样的查询系统封装的通用分页查询是不对的,所以需要自己sql中加入分页解决 SELECT you.nick_nam ...

  6. mysql 千万数据分页_MySQL处理千万级数据查询、分页

    MySQL数据库优化处理实现千万级快速分页分析,来看下吧. 数据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, ...

  7. mysql关联表分页查询_MySQL一对多分页查询-主表关联表条件查询问题

    文章目录 1 摘要 2 情景复现 2.1 数据模型 2.2 核心代码 2.3 测试数据 2.4 拓展一点 1 摘要 分页查询是后台项目中最常见的一种操作,在一对多(one to many)的关系表中, ...

  8. mysql分页查询出租房屋信息_分页查询信息(使用jdbc连接mysql数据库实现分页查询任务)...

    分页查询信息 使用jdbc连接mysql数据库实现分页查询任务 通过mysql数据库提供的分页机制,实现商品信息的分页查询功能,将查询到的信息显示到jsp页面上. 本项目时一个简单的运用eclipse ...

  9. Javaweb15==mysql+mybatis+servlet+axios+fasetjson+vue+elementUI前后端分离,实现列表后端分页、模糊查询后分页、新增、单一/批量删除、修改

    难点:模糊查询后再次分页,并可以选择页数. 最终环境配置: maven3.8:依赖包管理 IDEA2021+JDK8+mysql connector java5+Mysql5+mybatis3.5:从 ...

最新文章

  1. 常用正则表达式合集与工具
  2. SecurityManager安全管理器
  3. 简单的Ajax应用实例
  4. 分布式锁中的王者方案:Redisson
  5. mockito环境配置_Mockito –使用全局配置的SmartNull在NPE上提供更好的错误消息
  6. php为什么获取不到id,微信小程序无法获取到unionId怎么办
  7. 简单聊聊模型的性能评估标准
  8. 【Java每日一题】20170110
  9. python爬虫Day1(requests基本使用)
  10. mysql heartbeat keepalived_LVS+keepalived+DRBD+heartbeat+mysql
  11. 计算机二级等级考试ms office用什么软件练习好?
  12. SPF的最短路径算法
  13. 谢逸计算机网络,第一届中国计算机实践教育学术会议在南京成功举办
  14. rsa 生成密匙 ,密匙导出,加密解密封装
  15. 谷歌play支付_Google Play的新功能
  16. Window sqlite 客户端工具
  17. Blender展UV插件:UVSquares
  18. CDS TABLE FUNCTOIN传参,指定客户端
  19. css实现鼠标禁用(鼠标滑过显示红色禁止符号)
  20. 机器人学的数理基础知识

热门文章

  1. CNN 的一些可视化方法!
  2. sqoop数据迁移的应用
  3. 【原】IOS文件操作
  4. 从Java到Spring为何独得青睐Spring Summit 2017不可不知的那些事儿
  5. 英文版windows乱码问题(win7/8/10)
  6. Autolayout学习(1)-了解Autoreszing
  7. 在将对象数组转换为json字符串
  8. ORACLE数据库对比表结构
  9. .NET框架程序设计-.NET框架开发平台的体系架构概览(.NET程序本质)
  10. 防止办公用计算机,关于加强办公室计算机使用管理的规定