【问题标题】:Optimize a JOIN query, which "JOIN" would be the best?优化一个 JOIN 查询,哪个“JOIN”最好?
【发布时间】:2022-01-20 21:49:23
【问题描述】:

我有 2 张桌子:

表项

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

表格描述:

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 和 NAME 链接到 ITEM 表。(不可能有 2 个同名的项目,并且同一订单中的描述不同)。

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

  1. 我提出一个请求SELECT * FROM items WHERE ID_ORDER=2567,它返回给我一个List<Item>

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

    列出 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 件不同的商品,在第一次查询中我返回所有 1000 项商品,然后在第二次查询中我只返回 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# 仍然是更快的方法。

【问题讨论】:

  • @Zaki 感谢您的编辑,但您是如何制作这些表格的?将来可能有用
  • "SQL 有什么行为?"不清楚。 PS请通过编辑而不是cmets进行澄清。 PSminimal reproducible example
  • @philipxy 试图更好地解释,目前还不清楚我只是不知道该怎么做......我会删除这个问题,但因为有些人已经提供了帮助,我相信这对他们不公平。
  • 您仍然无法区分定义的结果与实现。 PS 始终尝试编辑帖子,但不要以使合理答案无效的方式。请注意,您已经有了像我链接的副本一样的答案。如果它有一个赞成或接受的答案,一个人不能删除自己的帖子。 PS 重新解释的问题(显然可以预期)也是重复的。在考虑发布问题之前,请先进行研究(包括阅读手册并使用“site:stackoverflow.com”进行谷歌搜索)。 PS请不要添加“EDIT”,在编辑时编辑到最好的演示文稿。

标签: c# sql join mariadb


【解决方案1】:

您可以使用 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

【讨论】:

    【解决方案2】:

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

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

    FROM a LEFT JOIN b ON ... WHERE b.id IS NULL 是查找a 行的模式,其中对应的b缺失`。

    RIGHT JOIN 是一个LEFT JOIN,表已交换。 (不要用这个,它会让我的大脑受伤。)

    CROSS JOIN 具有两个表的行的所有组合。这相当于在WHERE 子句中没有ON 和没有“关系”。

    “commajoin”是旧语法:FROM a,b WHERE a.foo=b.foo。不要使用它;如果你这样做,这个论坛上的响应者会拍你的手。

    关键字INNEROUTER 是无关紧要的,被 MySQL 忽略。

    FULL OUTER JOIN 是 MySQL 不支持的特性和语法。可以用JOINLEFT JOIN 结合UNION 进行模拟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多