Mat*_*ick 7 mysql innodb performance index query-performance
我有两个疑问,
select some_other_column
from `table`
order by primary_index_column asc
limit 4000000, 10;
Run Code Online (Sandbox Code Playgroud)
和
select some_other_column
from `table`
order by secondary_index_column asc
limit 4000000, 10;
Run Code Online (Sandbox Code Playgroud)
两者都返回 10 行;第一个需要 2.74 秒,第二个需要 7.07 秒。 some_other_column
不是任何索引的一部分。 primary_index_column
是主键列;secondary_index_column
有一个 b 树索引和 200 的基数(根据 MySQL)。
下面是explain
结果:
mysql> explain select some_other_column from `table` order by primary_index_column limit 4000000, 10;
+----+-------------+---------+-------+---------------+---------+---------+------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+------+---------+-------+
| 1 | SIMPLE | table | index | NULL | PRIMARY | 4 | NULL | 4000010 | |
+----+-------------+---------+-------+---------------+---------+---------+------+---------+-------+
mysql> explain select some_other_column from `table` order by secondary_index_column limit 4000000, 10;
+----+-------------+---------+------+---------------+------+---------+------+---------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+---------+----------------+
| 1 | SIMPLE | table | ALL | NULL | NULL | NULL | NULL | 4642945 | Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+---------+----------------+
Run Code Online (Sandbox Code Playgroud)
为什么 MySQL 为第二个查询选择特定的执行计划? 我不明白为什么它可以将索引用于第一个查询,但不能用于第二个查询。
InnoDB 中的索引列总是附加一个附加到gen_clust_index(又名聚集索引)的键。这将被第一个查询遍历以按索引顺序到达第 4000000 行。由于它是唯一被请求的列,因此不需要访问该表。
第二个查询必须将表中的非索引列与索引列一起收集到临时表中。然后在将非索引列显示为 SELECT 输出之前对临时表进行排序。
在这两种情况下,查询都指定要遍历的行数。由于表中的行数为 4636881,我们应该很容易期待一次完整的扫描。当 MySQL 查询优化器决定在何处执行完整扫描时,对比变得明显。
算一算,这里是 MySQL 查询优化器的计算结果:
老实说,根据表的行数、表的现有索引以及查询规定的行数,MySQL 查询优化器做出了正确的决定。
创建此索引
ALTER TABLE `table` ADD INDEX mynewndx (indexed_column,some_other_column);
Run Code Online (Sandbox Code Playgroud)
并且您的第二个查询将永远不会再次触及该表。当 MySQL 查询优化器看到这个新索引时,它的行为会大不相同。
归档时间: |
|
查看次数: |
3044 次 |
最近记录: |