为什么不同的主键查询在innodb中有巨大的速度差异?

Why different primary key queries have huge speed difference in innodb?

我有一个简单的 table Test:

而且我知道如果我 select id from Test,它将使用二级索引 id2 而不是 this post.

中所述的主索引(聚集索引)

如果我强制使用主索引进行查询,为什么选择不同的列时结果时间相差很大?

查询 1

select id, url from Test order by id limit 1000000, 1,仅使用 500ms+,这里是解释:

MySQL [x]> explain select id, url from Test order by id limit 1000000, 1;                                                                                                                                                                                        
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref  | rows    | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
|  1 | SIMPLE      | Test      | NULL       | index | NULL          | PRIMARY | 8       | NULL | 1000001 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
1 row in set, 1 warning (0.00 sec)

查询 2

select * from Test order by id limit 1000000, 1只用了2000ms+,下面是解释:

MySQL [x]> explain select * from Test order by ID limit 1000000, 1;                                                                                                                                                                                                     
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref  | rows    | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
|  1 | SIMPLE      | Test      | NULL       | index | NULL          | PRIMARY | 8       | NULL | 1000001 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+---------+----------+-------+
1 row in set, 1 warning (0.00 sec)

我看不出这两种解释有什么区别。那么为什么在结果时间上会有如此巨大的差异,因为它们使用相同的聚集索引?

  1. 查看sql个人资料,确定更多信息

mysql> 显示个人资料

2.mysql说明还不是很强大

3.What那种场景需要限制10000?

对于以下查询:

select id, url from t order by id limit 1000000, 1

MySQL 似乎 读取 1,000,000 行按 ID 排序而不是 跳过 它们。

我建议将查询更改为:

select * from t where id = (select id from t order by id limit 1000000, 1)

MySQL 似乎在将限制置于子查询内时跳过 1,000,000 行方面做得更好。

好吧,终于找到原因了……是因为mysqllimit的执行。 (不好意思我才找到这个中文解释,没有英文版)

在上面的查询 1 和查询 2 中,limit 执行以下操作:

  1. Mysql查询聚集索引,获取第一行;
  2. Mysql 会将第一行转换为结果;
  3. 然后在发送给客户端之前,Mysql发现有1000000的限制,所以第一行不是正确答案...
  4. Mysql 然后转到第 2 行并将其转换为结果;
  5. 然后在发送给客户端之前,Mysql发现有1000000的限制,所以第二行不是正确答案...;
  6. 周而复始,直到找到第1000001行,转换为结果后匹配limit 1000000, 1类;
  7. 所以最后,这是正确的答案,并发送给客户;

但是,它总共转换了1000000行。所以在上面的问题中,是'all fields conversion(select *) multiply 1000000 rows'与'one/two field conversion(select id/url) multiply 1000000 rows'之间的成本。毫无疑问,前者远比后者慢

不知道为什么 mysql limit 表现得如此笨拙,但它就是...