该sql是否命中MySql复合索引?

shi*_* xu 5 mysql composite-key query-performance

我有一张表: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   
Run Code Online (Sandbox Code Playgroud)

现在我有一个 Sql: select * from student_homework where student_id=100 and type=1结果explain如下:

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
Run Code Online (Sandbox Code Playgroud)

执行计划是uk_sid_lsnid_version

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

              student_id 
               /       \
           lesson_id     lesson_id
            /                      \  
     curriculum_version          curriculum_version
       /            \
      type         type
Run Code Online (Sandbox Code Playgroud)

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

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

Sha*_*dow 4

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

\n

提示在extra解释结果栏:使用索引条件

\n
\n

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

\n
\n
\n

通过访问索引元组并首先测试它们来确定是否读取完整的表行来读取表。这样,索引信息用于推迟(\xe2\x80\x9cpush down\xe2\x80\x9d)读取完整表行,除非有必要。请参见第 8.2.1.6 节,\xe2\x80\x9c索引条件下推优化\xe2\x80\x9d。

\n
\n

第 8.2.1.6 节,\xe2\x80\x9cIndex 条件下推优化将此技术的步骤描述为:

\n
\n
    \n
  1. 获取下一行的索引元组(但不是完整的表行)。
  2. \n
  3. 测试适用于该表的 WHERE 条件部分,并且可以仅使用索引列进行检查。如果不满足条件,则继续查找下一行的索引元组。
  4. \n
  5. 如果满足条件,则使用索引元组定位并读取全表行。
  6. \n
  7. 测试适用于此表的 WHERE 条件的剩余部分。根据测试结果接受或拒绝该行。
  8. \n
\n
\n

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

\n

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

\n