后端开发中为了防止⼀次性加载太多数据导致内存、磁盘IO都开销过⼤,经常需要分⻚展示,这个时候就需要⽤到MySQL的LIMIT关键字。但你以为LIMIT分⻚就万事大吉了么,LIMIT在数据量⼤的时候极可能造成深度分页问题。
例如,上图,我们在查user表时,mysql会先根据条件去磁盘检索得到符合条件的所有数据,然后在到内存中去做相应的排序和分页,最后得到一页数据返回,如果当我们数据达到千万级别时,仅用limit,当查询的条件多且大时,将会造成灾难性的后果,此时,我们如何解决呢?
例如,我们通过explain分析深度分⻚查询问题 **explain select * from user
where age>10 and age<90000000 order by age desc limit
8000000,10000;**执⾏计划Extra列可能出现的值及含义:
- Using where:表示优化器需要通过索引回表查询数据。
- Using index:即覆盖索引,表示直接访问索引就⾜够获取到所需要的数据,不需要通过索引回表,通常是通过将待查询字段建⽴联合索引实现。
- Using index condition:在5.6版本后加⼊的新特性,即⼤名鼎鼎的索引下推,是MySQL关于减少回表次数的重大优化。
- Using filesort:⽂件排序,这个⼀般在ORDER BY时候,数据量过大,MySQL会将所有数据召回内存中排序,比较消耗资源。
解决方案
通过主键索引优化
在查询条件中带上主键索引 explain select * from user where id>{maxId(即上一页最大的id} age>10 and age<90000000 order by
age desc limit 8000000,10000;
显然这种方法具有缺陷性,当我们的主键不是自增的,就会失效
2.Elastic Search搜索引擎优化(倒排索引)
实际上类似于淘宝这样的电商基本上都是把所有商品放进ES搜索引擎⾥的(那么海量的数据,放进MySQL是不可能的,放进Redis也不现实)。但即使⽤了ES搜索引擎,也还是有可能发⽣深度分⻚的问题的,这时怎么办呢?答案是通过游标scroll