【问题标题】:Left join or Select in select (SQL - Speed of query)左连接或选择中的选择(SQL - 查询速度)
【发布时间】:2016-11-27 05:51:55
【问题描述】:

我有这样的事情:

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万条记录有更好的速度? “select in select”还是“left join”?

【问题讨论】:

  • 如果性能是个问题,请尝试硬件上数据库中数据的每个版本,看看哪个更快。
  • 它有两个问题,我无法准备left join,对于大数据我无法测试它,因为我没有:(
  • 如果 MS SQL 为您执行此操作,请不要担心,因为它的优化器会优化您的查询。您可以在 companyId 上创建索引以帮助 MS SQL 更快地进行查询。

标签: sql select left-join inner-join


【解决方案1】:

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

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

除非您开始尝试解释计划,否则以上所有内容都只是反复试验。 Oracle 可以随心所欲地在 LEFT JOININ SELECT 之间进行转换。超过 100 万行将为投资创造时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多