优化 JOIN 查询,哪个 "JOIN" 最好?

Optimize a JOIN query, which "JOIN" would be the best?

我有 2 tables :

Table 项目

ID ID_ORDER ID_BOX NAME
001 2564 123 SPOON_1
002 2564 123 SPOON_2
006 2564 123 SHOES_2
007 2564 123 SHOES_1
003 2565 124 SPOON_1
004 2565 124 SPOON_2
008 2565 124 SHOES_1
009 2565 124 SHOES_2
005 2565 125 SPOON_1
010 2565 125 SHOES_1

Table 说明:

ID_ORDER NAME LENGTH WIDTH ....
2564 SPOON_1 200 20 ...
2564 SPOON_2 300 20 ...
2564 SHOES_1 500 20 ...
2564 SHOES_2 600 20 ...

对象的描述通过 ID_ORDER 和名称链接到项目 table。(不可能有 2 个名称相同的项目,但在同一订单中有不同的描述)。

我发现更快的方法是使用 C#(我比较了所有时间):

  1. 我提出请求 SELECT * FROM items WHERE ID_ORDER=2567,return 是我 List<Item>

  2. 然后我按名称分组,以在列表中包含项目名称列表:

    List listNames=listItems.Select(x=>"'"+x.Name+"'").Distinct().ToList();

  3. 我发出第二个请求,将查找所有对应的描述:

    string query = "SELECT * FROM description WHERE ID_ORDER=2567 AND NAME IN ("+string.Join(",",listNames)+")";

即使我的订单中有 1000 件商品,但只有 50 件不同的商品,在第一次查询中我 return 所有 1000 件商品,然后在第二次查询中我 return 只有 50 条描述。

所以最后我只需要做类似的事情:

foreach(Item item in listItems)
{
    item.Description=listDescriptions.FirstOrDefault(x=>x.Name==item.Name);
}

现在,我试图在一个 SQL 请求中完成所有工作。这是我现在拥有的:

SELECT * FROM items INNER JOIN description 
ON (description.ID_ORDER=items.ID_ORDER AND description.NAME=items.NAME) 
WHERE ID_ORDER= 2564

据我了解,问题是 SQL 将搜索项目列表,然后将搜索每个项目的描述,并且看起来更多时间,因为描述是大数据。 有没有更快的方法让 SQL 首先读取与我的项目列表对应的所有描述,然后将描述应用于每个项目?我也试过 RIGHT JOIN(我相信它会那样做),但它花费的时间几乎和简单的 JOIN 一样多,使用 C# 仍然是更快的方法。

您可以使用 EXPLAIN 命令,它会让您知道 MySQL 计划如何回答您的查询。您可以使用它来优化您的查询 运行 更快,或者只是为了了解它是如何工作的。参见 https://dev.mysql.com/doc/refman/8.0/en/explain.html

例如:

EXPLAIN SELECT * FROM items INNER JOIN description 
ON (description.ID_ORDER=items.ID_ORDER AND description.NAME=items.NAME) 
WHERE ID_ORDER=2564

JOIN 包括根据 ON 匹配的 table 和 行。 (或者关系可能隐藏在不属于它们的 WHERE 中。WHERE 应该仅用于过滤。)

LEFT JOIN 包括“左”table 的所有行和“右”table 的任何匹配行,无论它们是否匹配。不匹配的行在列中显示 NULL

FROM a LEFT JOIN b ON ... WHERE b.id IS NULL 是用于查找 a 行的模式,对应的 b 行是 missing`。

RIGHT JOIN 是交换了 table 的 LEFT JOIN。 (别用这个,我脑袋疼。)

CROSS JOIN 具有两个 table 行的所有组合。相当于WHERE子句中没有ON,也没有'relationship'。

“commajoin”是旧语法:FROM a,b WHERE a.foo=b.foo。不要使用它;如果你这样做,本论坛的回复者会打你的手。

关键字 INNEROUTER 不相关并被 MySQL 忽略

FULL OUTER JOIN 是 MySQL 不支持的功能和语法。它可以用 JOINLEFT JOIN 结合 UNION.

来模拟