MySQL
分页的基本原理:
SELECT FROM test ORDER BY id DESC LIMIT 10000, 20;LIMIT 10000 , 20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行。如果是LIMIT 1000000 , 100,需要扫描1000100 行,在一个高并发的应用里,每次查询需要扫描超过100W。
ElasticSearch
从业务的角度来说,ElasticSearch不是典型的数据库,它是一个搜索引擎,如果在筛选条件下没有搜索出想要的数据,继续深度分页也不会找到想要的数据,退一步讲,假如我们把ES作为数据库来使用进行查询,在进行分页的时候一定会遇到max_result_window的限制,看到没,官方都告诉你最大偏移量限制是一万。
查询流程:
1.如查询第501页,每页10条,客户端发送请求到某节点
2.此节点将数据广播到各个分片,各分片各自查询前 5010 条数据查询结果返回至该节点,
3.然后对数据进行整合,取出前 5010 条数据
*4.返回给客户端
解决方案
原分页SQL:
# 第一页SELECT FROM year_score where year = 2017 ORDER BY id limit 0, 20;# 第N页SELECT FROM year_score where year = 2017 ORDER BY id limit (N - 1) 20, 20; 通过上下文关系,改写为:
# XXXX 代表已知的数据SELECT FROM year_score where year = 2017 and id > XXXX ORDER BY id limit 20;SQL优化和诊断 一文中提到过,LIMIT会在满足条件下停止查询,因此该方案的扫描总量会急剧减少,效率提升Max!
ES
方案和MySQL相同,此时我们就可以随心所欲的使用 FROM-TO Api,而且不用考虑最大限制的问题。
在 SQL优化一文中还提到过MySQL深度分页的处理技巧,代码如下:
# 反例(耗时129.570s)select from task_result LIMIT 20000000, 10;# 正例(耗时5.114s)SELECT a. FROM task_result a, (select id from task_result LIMIT 20000000, 10) b where a.id = b.id;# 说明# task_result表为生产环境的一个表,总数据量为3400万,id为主键,偏移量达到2000万该方案的核心逻辑即基于聚簇索引,在不通过回表的情况下,快速拿到指定偏移量数据的主键ID,然后利用聚簇索引进行回表查询,此时总量仅为10条,效率很高。
