【问题标题】:Is MySql composite index hit for this sql?此 sql 是否命中 MySql 复合索引?
【发布时间】:2020-08-23 12:29:23
【问题描述】:

我有一张表:student_homework,它的复合索引之一是uk_sid_lsnid_version(student_id, lesson_id, curriculum_version, type)

student_homework    0   uk_sid_lsnid_version    1   student_id  A   100             BTREE       
student_homework    0   uk_sid_lsnid_version    2   lesson_id   A   100             BTREE       
student_homework    0   uk_sid_lsnid_version    3   curriculum_version  A   100             BTREE       
student_homework    0   uk_sid_lsnid_version    4   type    A   100             BTREE   

现在我有一个 Sql: select * from student_homework where student_id=100 and type=1explain 结果是这样的:

1   SIMPLE  student_homework        ref uk_sid_lsnid_version,idx_student_id_update_time uk_sid_lsnid_version    4   const   20  10.0    Using index condition

执行计划是uk_sid_lsnid_version

我的问题是查询条件type 在这里如何工作?数据库引擎是否扫描所有(缩小的)记录?在我的理解中,树的层次结构是:

              student_id 
               /       \
           lesson_id     lesson_id
            /                      \  
     curriculum_version          curriculum_version
       /            \
      type         type

对于查询条件(student_id, type)student_id匹配树索引的根。然而,type 与索引 lesson_id 不匹配,数据库引擎将在 所有记录 上应用 type,这些记录已被 student_id 过滤。

  1. 我的理解正确吗?如果带有student_id 的子集记录很大,则查询成本仍然很高。
  2. 查询条件student_id = 100 and type =0type=0 and student_id = 100没有区别
  3. 为了充分利用复合索引,如果我添加一个新的复合索引会更好(student_id, type)

【问题讨论】:

  • 是的,做一个复合索引,但仍然用不同的索引测试查询,看看eh性能是否变得更好
  • 请提供SHOW CREATE TABLE;我们需要比你提供的更多的细节。
  • 只能使用INDEX最左边列;没有跳过列。 WHERE 的顺序无关紧要。更多:mysql.rjweb.org/doc.php/index_cookbook_mysql

标签: mysql query-performance composite-key


【解决方案1】:

是的,你的理解是正确的,mysql 将使用uk_sid_lsnid_version 索引仅匹配student_id,而对type 的过滤将在减少匹配student_id 的行集上进行。

提示在解释结果的extra列中:Using index condition

使用索引条件(JSON 属性:using_index_condition)

通过访问索引元组并首先测试它们以确定是否读取完整的表行来读取表。这样,除非有必要,否则索引信息用于延迟(“下推”)读取全表行。请参阅第 8.2.1.6 节,“索引条件下推优化”。

Section 8.2.1.6, “Index Condition Pushdown Optimization 将该技术的步骤描述为:

  1. 获取下一行的索引元组(但不是整个表行)。
  2. 测试适用于该表的 WHERE 条件部分,并且只能使用索引列进行检查。如果条件不是 满意,继续下一行的索引元组。
  3. 如果条件满足,使用索引元组定位并读取全表行。
  4. 测试适用于该表的 WHERE 条件的剩余部分。根据测试结果接受或拒绝该行。

在student_id上加一个复合索引是否更好,type是我们无法客观回答的问题,你需要测试一下。

如果使用当前索引的查询速度很好,那么您可能不需要新索引。您还需要权衡有多少其他查询会使用该索引 - 仅为一个查询创建索引没有多大意义。您还需要权衡type 字段的选择性。具有有限值列表的类型字段通常没有足够的选择性。由于student_id,mysql可能决定使用索引条件下推,类型索引不是覆盖索引,mysql无论如何都必须获取整行。

【讨论】:

  • ICP是二次优化。最好在可行时重新排列列(或添加新索引)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多