简单一点描述:limit%20100000,20%20的意思扫描满足条件的%20100020%20行,扔掉前面的%20100000%20行,返回最后的%2020%20行,问题就在这里 。如果我反向查询%20oder%20by%20xx%20desc%20limit%200,20,那么我只要索引%2020%20条数据 。
Example%203
mysql>%20select%20count(*)%20from%20elastic_task_log_copy;+----------+|%20count(*)%20|+----------+|%201705162%20|+----------+1%20rows%20in%20set%20(2.31%20sec)正向偏移查询 。超级浪费的查询,需要先%20skip%20大量的符合条件的查询 。
mysql>%20select%20id%20from%20elastic_task_log_copy%20order%20by%20id%20asc%20limit%201705152,10;+---------+|%20id%20|+---------+|%201705157%20||%201705158%20||%201705159%20||%201705160%20||%201705161%20||%201705162%20||%201705163%20||%201705164%20||%201705165%20||%201705166%20|+---------+10%20rows%20in%20set%20(2.97%20sec)反向偏移查询 。同样的查询结果,千差万别的结果 。
mysql>%20select%20id%20from%20elastic_task_log_copy%20order%20by%20id%20desc%20limit%200,10;+---------+|%20id%20|+---------+|%201705166%20||%201705165%20||%201705164%20||%201705163%20||%201705162%20||%201705161%20||%201705160%20||%201705159%20||%201705158%20||%201705157%20|+---------+10%20rows%20in%20set%20(0.01%20sec)这两条%20sql%20是为查询最后一页的翻页%20sql%20查询用的 。由于一次翻页往往只需要查询较小的数据,如%2010%20条,但需要向后扫描大量的数据,也就是越往后的翻页查询,扫描的数据量会越多,查询的速度也就越来越慢 。
由于查询的数据量大小是固定的,如果查询速度不受翻页的页数影响,或者影响最低,那么这样是最佳的效果了(查询最后最几页的速度和开始几页的速度一致) 。
在翻页的时候,往往需要对其中的某个字段做排序(这个字段在索引中),升序排序 。那么可不可以利用索引的有序性%20来解决上面遇到的问题 。
比如有%2010000%20条数据需要做分页,那么前%205000%20条做%20asc%20排序,后%205000%20条%20desc%20排序,在%20limit%20startnum,pagesize%20参数中作出相应的调整 。
但是这无疑给应用程序带来复杂,这条%20sql%20是用于论坛回复帖子的%20sql,往往用户在看帖子的时候,一般都是查看前几页和最后几页,那么在翻页的时候最后几页的翻页查询采用%20desc%20的方式来实现翻页,这样就可以较好的提高性能 。
游标:上一页的最大值或者最小值
如果你知道上一页和下一页的临界值,那么翻页查询也是信手拈来了,直接就告诉了数据库我的起始查询在哪,也就没有什么性能问题了 。我更愿意称这个东西为游标%20(Cursor) 。
如果做下拉刷新,那么就直接避免掉分页的问题了 。根据上一页的最后一个值去请求新数据 。
mysql>%20select%20id%20from%20elastic_task_log_copy%20where%20id%20>=%201699999%20limit%2010;+---------+|%20id%20|+---------+|%201699999%20||%201700000%20||%201700001%20||%201700002%20||%201700003%20||%201700004%20||%201700005%20||%201700006%20||%201700007%20||%201700008%20|+---------+10%20rows%20in%20set%20(0.01%20sec)缓存和不精准
数据量达到一定程度的时候,用户根本就不关心精准的总数,%20没人关心差几个 。看看知乎、微博、微信订阅号,不精准的统计到处都是 。
如果每次点击分页的时候都进行一次%20count%20操作,那速度肯定不会快到哪里去 。他们一般也是采用计数器的办法 。每次新增加一个粉丝,就把值加%201,直接在用户信息存储一个总数,一段时间后重新查询一次,更新该缓存 。这样分页的时候直接拿这个总数进行分页,显示的时候直接显示模糊之就行 。
那为什么微信公众号的阅读量只有%2010W+%20这个量级呢?100W+%20级去哪了!
5.%20其他的建议
1、mysql%20的数据查询,%20大小字段要分开,%20这个还是有必要的,%20除非一点就是你查询的都是索引内容而不是表内容,%20比如只查询%20id%20等等
2、查询速度和索引有很大关系也就是索引的大小直接影响你的查询效果,%20但是查询条件一定要建立索引,%20这点上注意的是索引字段不能太多,太多索引文件就会很大那样搜索只能变慢,
3、查询指定的记录最好通过%20Id%20进行%20in%20查询来获得真实的数据.%20其实不是最好而是必须,也就是你应该先查询出复合的%20ID%20列表,%20通过%20in%20查询来获得数据
4、mysql%20千万级别数据肯定是没问题的,%20毕竟现在的流向%20web2.0%20网站大部分是%20mysql%20的
5、合理分表也是必须的,%20主要涉及横向分表与纵向分表,%20如把大小字段分开,%20或者每%20100%20万条记录在一张表中等等,%20像上面的这个表可以考虑通过%20uid%20的范围分表,%20或者通过只建立索引表,%20去掉相对大的字段来处理.
推荐阅读
- Java性能优化-掌握JMH
- 手机2G 3G 4G 5G 通信基站架构演进
- 微服务架构下的分布式事务基础入门
- 微服务架构下:MySQL5.7新特性--官方高可用方案MGR介绍
- JAVA的反射和注解
- Java缓冲流、转换流、序列化流
- 关于JavaScript及其对抓取和索引的影响
- 5大Java自动化测试框架
- 全面解析Java日期时间API
- 35个可以飞快提高千倍效率的Java语言代码小技巧,你值得拥有!
