选择左连接或选择(SQL - 查询速度)

时间:2016-07-23 11:50:34

标签: sql select left-join inner-join

我有这样的事情:

SELECT CompanyId 
FROM Company
WHERE CompanyId not in
    (SELECT CompanyId 
     FROM Company 
     WHERE (IsPublic = 0) and CompanyId NOT IN 
         (SELECT ShoppingLike.WhichId 
          FROM Company 
          INNER JOIN 
          ShoppingLike ON Company.CompanyId = ShoppingLike.UserId 
          WHERE (ShoppingLike.IsWaiting = 0) AND
                (ShoppingLike.ShoppingScoreTypeId = 2) AND
                (ShoppingLike.UserId = 75)
          )
     )

它有3个选择,我想知道如何在不进行3次选择的情况下拥有它,哪一个拥有100万条记录的更快速度? "选择"或者"左连接"?

1 个答案:

答案 0 :(得分:0)

我的经验来自Oracle。优化棘手的查询从来没有正确的答案,这是您和优化者之间的合作。您需要检查解释计划,有时还要检查跟踪,通常是在编写查询的每个阶段,以找出优化者的想法。话虽如此:

  • 您可以通过在SELECT ... WHERE中放置其子查询NOT(子句的全部内容来删除外部)。从表面上看,它将阻止公司的外部全面扫描(或它的CompanyId指数)。尝试一下,检查输出是否相同并获得时间,然后在尝试下面之前暂时将其删除。由于隐式OR被创建,NOT()可能会导致优化器停止考虑针对ShoppingLike子查询的ANTI-JOIN。
  • 确保将CompanyId和WhichId定义为NOT NULL列。如果没有这个(或类似于显式CompanyId IS NOT NULL),则通常会丢弃ANTI-JOIN选项。
  • 最内层子查询不相关(不引用其外部查询中的任何内容),因此可以单独提取和调整。作为一种风格问题,我会将表名称替换为INNER JOIN,因为您希望ShoppingLike首先扫描,因为它具有针对它的所有过滤器。它不会有任何区别,但它读起来更容易,并且可以使用提示按指定的顺序扫描表。我甚至会质疑这个子查询中公司表的必要性。
  • 您曾使用NOT IN,有时非常相似NOT EXISTS会为优化工具提供更多/替代选项。

除非您开始尝试解释计划,否则上述所有内容都只是反复试验。 Oracle可以随后在LEFT JOININ SELECT之间进行转换。 1M +行将创造投资时间。

相关问题