MySQL中是否有Index "hopping"之类的东西?
Is there such thing as Index "hopping" in MySQL?
假设我们在 (A, B) 上有一个索引,在 (B, C) 上有一个索引。进行如下查询时:
SELECT * FROM table WHERE A = const AND B = const ORDER BY C DESC
查询优化器是否会先在(A,B)索引中搜索过滤WHERE行class,然后再使用(B,C)索引快速排序?
或者查询仅限于一个索引?没有 B 树跳跃?
当然,您可以测试您的数据。但根据我的经验,索引将首先匹配 where
子句。因此,它将匹配 (A, B)
索引。
然后它将对排序进行排序。
不,MySQL 不符合您的描述。
它将执行以下操作之一:
从 (A, B)
索引读取,它将使用索引仅检查匹配的行,但需要额外的工作来执行文件排序以按 [=12= 对行进行排序].
从 (B, C)
索引读取,它将以正确的顺序读取行,因此跳过文件排序。但它会检查许多额外的行,这些行的值 A
不匹配,并且它必须逐一评估这些行并丢弃那些不匹配的行。
您可以通过将 (A, B)
索引替换为 (A, B, C)
上的索引来优化两者,这将只检查匹配的行,并以所需的顺序读取它们,因此不需要文件排序.
InnoDB 总是以某种索引顺序读取行。二级索引或聚簇索引。
回复您的问题:
通常,MySQL 每个 table 引用仅从一个索引读取。这允许例如使用自连接的查询,因此对于相同的 table 有多个 table 引用。每个 table 引用可能使用不同的索引读取。
例如,经理与其员工的自连接:
SELECT ...
FROM employees AS m
JOIN employees AS e ON e.manager_id = m.id
WHERE m.hire_date = '2020-01-01'
在此示例中,它可能使用 hire_date
上的索引到 select 经理,以及 manager_id
上的索引以供经理的下属使用。这是两个不同的 table 参考文献,因此分开阅读。
还有一个 MySQL 的特性称为 index merge optimization,它可能会读取 table 的两个子集,可能使用不同的索引,然后使用任一并集合并结果或交叉路口。但我发现这种情况并不像您想象的那样经常发生。
关于 ORDER BY DESC,https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html 说:
previously, indexes could be scanned in reverse order but at a performance penalty.
在 MySQL 8.0 中,他们实现了对声明要按降序构建的索引的支持,以支持 ORDER BY DESC 查询。但是索引是为这些查询量身定制的,并且对 ASC 查询使用相同的索引会受到影响。因此,您可能需要在相同 table 的相同列上创建两个索引。阅读我链接到的文档页面以获取更多详细信息。
你问:
Will the query optimizer first search in the (A,B) index to filter the rows for the WHERE class?
是的,MySQL 可能会使用第一个索引来检索行,如果谓词匹配 UNIQUE
约束。
...and then subsequently use the (B, C) index to sort quickly?
没有。第二个索引不包括使用第一个索引过滤的行。引擎将检索所有行(不再使用流水线),对它们进行排序,然后将它们提供给您。如果有很多行,这个阶段将是资源密集型和缓慢的。希望过滤谓词只产生几行。
假设我们在 (A, B) 上有一个索引,在 (B, C) 上有一个索引。进行如下查询时:
SELECT * FROM table WHERE A = const AND B = const ORDER BY C DESC
查询优化器是否会先在(A,B)索引中搜索过滤WHERE行class,然后再使用(B,C)索引快速排序?
或者查询仅限于一个索引?没有 B 树跳跃?
当然,您可以测试您的数据。但根据我的经验,索引将首先匹配 where
子句。因此,它将匹配 (A, B)
索引。
然后它将对排序进行排序。
不,MySQL 不符合您的描述。
它将执行以下操作之一:
从
(A, B)
索引读取,它将使用索引仅检查匹配的行,但需要额外的工作来执行文件排序以按 [=12= 对行进行排序].从
(B, C)
索引读取,它将以正确的顺序读取行,因此跳过文件排序。但它会检查许多额外的行,这些行的值A
不匹配,并且它必须逐一评估这些行并丢弃那些不匹配的行。
您可以通过将 (A, B)
索引替换为 (A, B, C)
上的索引来优化两者,这将只检查匹配的行,并以所需的顺序读取它们,因此不需要文件排序.
InnoDB 总是以某种索引顺序读取行。二级索引或聚簇索引。
回复您的问题:
通常,MySQL 每个 table 引用仅从一个索引读取。这允许例如使用自连接的查询,因此对于相同的 table 有多个 table 引用。每个 table 引用可能使用不同的索引读取。
例如,经理与其员工的自连接:
SELECT ...
FROM employees AS m
JOIN employees AS e ON e.manager_id = m.id
WHERE m.hire_date = '2020-01-01'
在此示例中,它可能使用 hire_date
上的索引到 select 经理,以及 manager_id
上的索引以供经理的下属使用。这是两个不同的 table 参考文献,因此分开阅读。
还有一个 MySQL 的特性称为 index merge optimization,它可能会读取 table 的两个子集,可能使用不同的索引,然后使用任一并集合并结果或交叉路口。但我发现这种情况并不像您想象的那样经常发生。
关于 ORDER BY DESC,https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html 说:
previously, indexes could be scanned in reverse order but at a performance penalty.
在 MySQL 8.0 中,他们实现了对声明要按降序构建的索引的支持,以支持 ORDER BY DESC 查询。但是索引是为这些查询量身定制的,并且对 ASC 查询使用相同的索引会受到影响。因此,您可能需要在相同 table 的相同列上创建两个索引。阅读我链接到的文档页面以获取更多详细信息。
你问:
Will the query optimizer first search in the (A,B) index to filter the rows for the WHERE class?
是的,MySQL 可能会使用第一个索引来检索行,如果谓词匹配 UNIQUE
约束。
...and then subsequently use the (B, C) index to sort quickly?
没有。第二个索引不包括使用第一个索引过滤的行。引擎将检索所有行(不再使用流水线),对它们进行排序,然后将它们提供给您。如果有很多行,这个阶段将是资源密集型和缓慢的。希望过滤谓词只产生几行。