比如我们的建表sql是这样的
只需要知道id是主键,并且在user_name建了个非主键索引就够了,其他都不重要。
为了实现分页。很容易联想到下面这样的sql语句。
select * from page order by id limit offset, size;
比如一页有10条数据。user表数据库原始状态,第一页就是下面这样的sql语句。
select * from page order by id limit 0, 10;
第一百页就是
select * from page order by id limit 990, 10;
那么问题来了。用这种方式,同样都是拿10条数据,查第一页和第一百页的查询速度是一样的吗?为什么?
两种limit的执行过程
上面的两种查询方式。对应 limit offset, size
和 limit size
两种方式。
而其实 limit size
,相当于 limit 0, size
。也就是从0开始取size条数据。
也就是说,两种方式的区别在于offset是否为0。
我们先来看下limit sql的内部执行逻辑。
Mysql架构
mysql内部分为server层和存储引擎层。一般情况下存储引擎都用innodb。
server层有很多模块,其中需要关注的是执行器是用于跟存储引擎打交道的组件。
执行器可以通过调用存储引擎提供的接口,将一行行数据取出,当这些数据完全符合要求(比如满足其他where条件),则会放到结果集中,最后返回给调用mysql的客户端(go、java写的应用程序)。
我们可以对下面的sql先执行下 explain
。
explain select * from page order by id limit 0, 10;
可以看到,explain中提示 key 那里,执行的是PRIMARY,也就是走的主键索引。
分页查询offset=0
主键索引本质是一棵B+树,它是放在innodb中的一个数据结构。
我们可以回忆下,B