关于条件的MySQL左连接顺序

关于条件的MySQL左连接顺序,mysql,sql,join,left-join,Mysql,Sql,Join,Left Join,我有一个MySQL查询,包含内部连接和一个左连接,数据库中有很多数据,运行速度非常慢。这大概是我的疑问: SELECT main_table.* FROM main_table INNER JOIN ... LEFT JOIN second_table ON (main_table.id = second_table.ref_id AND second_table.type = 'foo' AND second_table.bar IS NULL WHERE

我有一个MySQL查询,包含内部连接和一个左连接,数据库中有很多数据,运行速度非常慢。这大概是我的疑问:

SELECT
    main_table.*
FROM
    main_table
INNER JOIN
    ...
LEFT JOIN
    second_table ON (main_table.id = second_table.ref_id AND second_table.type = 'foo' AND second_table.bar IS NULL
WHERE
    second_table.id IS NULL
;
main\u表
中的条目在
second\u表
中可能有一个或多个引用条目。我想从
主表
中获取所有结果,这些结果要么在
第二个表
中没有结果,要么在第二个表中只有不相关的数据(
键入'foo'
为空)

查看解释,MySQL首先搜索
bar为NULL,然后搜索
type='foo'
,这仍然会导致数千个结果,而首先检查
ref\u id
只会留下很少的结果来检查其他条件

我只有
ref\u id
上的索引,而不是
type
bar
上的索引,如果我可以先获得
ref\u id
的查询搜索,我觉得没有必要对它们进行索引

--编辑:我注意到在数据库的副本上(它有实际的数据并且运行缓慢),也有一个关于
type
bar
的索引,所以这可能是MySQL喜欢
bar
而不是其他键的原因。我正在考虑一个跨越多个字段的键--

有人知道如何优化这种查询吗?是否可以在ON条件下强制MySQL使用特定顺序


“解决方案”:我添加了一个覆盖所有相关字段的索引


我不认为这是一个真正的解决方案,因为我相信,如果在索引<代码> RefIDID < /代码>上完成连接,也会更快。当这是唯一的索引时,它可能会这样做,但是我的同事有一个想法,在其他字段上单独添加一个索引,出于某种原因,可能需要在我们的应用程序中的其他地方添加索引。

如果将“不相关”行移动到where部分,会发生什么? 在我看来,DB应该更容易加入表,并将使用索引

差不多

SELECT
    main_table.*
FROM
    main_table
INNER JOIN
    ...
LEFT JOIN
    second_table ON main_table.id = second_table.ref_id 
WHERE
    second_table.id IS NULL OR 
    (second_table.type = 'foo' AND second_table.bar IS NULL)

在MYSQL中,
JOIN
LEFT JOIN
更快,所以您可以这样编写查询

SELECT
    main_table.*
FROM
    main_table
INNER JOIN
    ...
LEFT JOIN (SELECT main_table.*,second_table.*  FROM main_table 

JOIN second_table ON main_table.id = second_table.ref_id AND

second_table.type = 'foo' AND second_table.bar IS NULL) AS main_table2 ON 

main_table2.id = main_table.id

WHERE
second_table.id IS NULL;

即使您可以保证订单,但我认为您不能,如果您更改查询,接下来会发生什么?然后,订单可以再次更改。为什么不在任何有用的地方添加一个索引呢?我不会用“想要”这个词来回答问题。这只是一条规则。在第二个表的所有三列上添加一个索引,然后检查结果。索引中的ref_id、type和bar列的顺序应该是这样的。有一种方法可以提示MySQL使用某些索引,尽管我怀疑您的问题应该通过其他方式解决,但使用提示并不常见。这可能对某些人有用:这也是我首先想到的。您的查询包括
type='foo'
,但我需要在最终结果中排除它们(注意我的
,其中第二个\u table.id为NULL
)。如果第二个表中只有一个匹配项与条件匹配,我想排除主结果。您的意思是,如果主表中的一行有1个相关行和1个非相关行,它不应该出现在结果中,但我的查询将包含它。对吧?没错,就是这样。