MySQL专家:为什么两个查询给出不同的“解释”索引使用结果?

MySQL专家:为什么两个查询给出不同的“解释”索引使用结果?,mysql,sql,optimization,Mysql,Sql,Optimization,此查询: explain SELECT `Lineitem`.`id`, `Donation`.`id`, `Donation`.`order_line_id` FROM `order_line` AS `Lineitem` LEFT JOIN `donations` AS `Donation` ON (`Donation`.`order_line_id` = `Lineitem`.`id`) WHERE `Lineitem`.`session_id`

此查询:

explain 
SELECT `Lineitem`.`id`, `Donation`.`id`, `Donation`.`order_line_id` 
  FROM `order_line` AS `Lineitem` 
       LEFT JOIN `donations` AS `Donation` 
       ON (`Donation`.`order_line_id` = `Lineitem`.`id`) 
 WHERE `Lineitem`.`session_id` = '1'
正确使用generation.order\u line\u id和Lineitem.id索引,如本解释输出所示:

id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Lineitem ref session_id session_id 97 const 1 Using where; Using index 1 SIMPLE Donation ref order_line_id order_line_id 4 Lineitem.id 2 Using index 显示捐赠表不使用索引:

id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Lineitem ref session_id session_id 97 const 1 Using where; Using index 1 SIMPLE Donation ALL order_line_id NULL NULL NULL 3 我也读了一些关于基数的书,看起来像是捐款。npo_id和捐款。order_line_id的基数都是2。希望这能说明一些有用的东西

我认为使用索引可能会解决这个问题,但我使用的ORM让这个问题变得有点棘手,我不明白为什么当连接专门命名索引字段时它不能获取正确的索引


谢谢你的智慧

第一个解释在结尾使用了索引。这意味着它只需查看索引,而不必获取/分析任何行数据,就可以找到行并返回查询结果

在第二个查询中,您添加了一个可能没有索引的行。这意味着MySQL必须查看表的数据。我不知道为什么乐观主义者选择了表格扫描,但我认为,如果表格相当小,那么它很可能更容易读取所有内容,而不是试图为单个行挑选细节

编辑:我认为添加以下索引将使情况得到更大的改善,并让所有联接只使用索引:

ALTER TABLE order_line ADD INDEX(session_id, id);
ALTER TABLE donations ADD INDEX(order_line_id, npo_id, id)
这将允许order_line使用session_id查找行,然后返回id,还允许捐赠加入order_line_id,然后返回其他两列


查看自动增量值,我可以假设其中没有太多数据。值得注意的是,表中的数据量会对查询计划产生影响,最好将一些示例数据放在其中进行测试。想了解更多细节,请看我不久前写的这篇博文:

第一篇解释在结尾使用了索引。这意味着它只需查看索引,而不必获取/分析任何行数据,就可以找到行并返回查询结果

在第二个查询中,您添加了一个可能没有索引的行。这意味着MySQL必须查看表的数据。我不知道为什么乐观主义者选择了表格扫描,但我认为,如果表格相当小,那么它很可能更容易读取所有内容,而不是试图为单个行挑选细节

编辑:我认为添加以下索引将使情况得到更大的改善,并让所有联接只使用索引:

ALTER TABLE order_line ADD INDEX(session_id, id);
ALTER TABLE donations ADD INDEX(order_line_id, npo_id, id)
这将允许order_line使用session_id查找行,然后返回id,还允许捐赠加入order_line_id,然后返回其他两列


查看自动增量值,我可以假设其中没有太多数据。值得注意的是,表中的数据量会对查询计划产生影响,最好将一些示例数据放在其中进行测试。要了解更多详细信息,请查看我不久前写的这篇博文:

实际上,这可能不是100%正确。你能为这些表添加showcreatetable和完整的解释输出吗?仅仅添加第二个索引就行了,尽管我不明白为什么。所有这三个id都被索引了。为什么创建一个由这些id组成的索引时忽略了order_line_id索引?我认为发生这种情况的原因是优化器认为使用单个索引没有好处。随着桌子越来越大,我会注意这个。谢谢对于每个打开的表,MySQL只能使用其中一个索引,因此您需要通过创建复合索引来使用尾部索引,从而允许MySQL查找索引左侧的行,然后使用右侧更多的列来获取数据。这是因为B树索引的存储方式。实际上,这可能不是100%正确。你能为这些表添加showcreatetable和完整的解释输出吗?仅仅添加第二个索引就行了,尽管我不明白为什么。所有这三个id都被索引了。为什么创建一个由这些id组成的索引时忽略了order_line_id索引?我认为发生这种情况的原因是优化器认为使用单个索引没有好处。随着桌子越来越大,我会注意这个。谢谢对于每个打开的表,MySQL只能使用其中一个索引,因此您需要通过创建复合索引来使用尾部索引,从而允许MySQL查找索引左侧的行,然后使用右侧更多的列来获取数据。这是由于B树索引的存储方式。
ALTER TABLE order_line ADD INDEX(session_id, id);
ALTER TABLE donations ADD INDEX(order_line_id, npo_id, id)