【问题标题】:INNER JOIN slowing down the queryINNER JOIN 减慢查询速度
【发布时间】:2015-11-27 19:37:29
【问题描述】:

我有一个像这样的内部连接:

INNER JOIN Area AS area ON (Area.Id = psaLocalityOrCity.AreaId OR Area.Id = psaDbl.AreaId)

psaLocalityOrCity 是我需要区域的位置,但是有些记录在 psaLocalityOrCity 中重复。这些,并且只有这些,已作为单个记录提取到 psaDbl 中。上面的 INNER JOIN 假设可以找到两个组中所有地区的所有区域,但是这个 OR 语句导致它运行了很长时间。那会是什么原因呢?是否有任何修复可以优化查询以再次运行 6 秒而不是 3 分钟?

【问题讨论】:

  • INNER JOIN with OR 难怪它很慢,查看执行计划并检查它是否使用索引或执行全表扫描
  • 显示所有查询,试试WITH cte AS (SELECT * FROM psaLocalityOrCity UNION ALL SELECT * FROM psaDbl) SELECT * FROM tab JOIN cte,当然用列名替换*
  • 检查该 id 的类型是否相同。在这些情况下,隐式转换是导致速度缓慢的第一大原因。原因 #2 不好或缺少索引

标签: sql tsql join inner-join


【解决方案1】:

INNER JOINOR 将导致嵌套循环连接,这是最慢的一种。一种方法是使用UNION ALL,如评论中所建议的那样。另一种是使用两个LEFT JOINs。结构示例:

SELECT . . .,
       COALESCE(aloc.col1, adbl.col1)
FROM psaLocalityOrCity loc LEFT JOIN
     Area aloc
     ON aloc.Id = loc.AreaId LEFT JOIN
     Area adbl
     ON adbl.Id = psaDbl.AreaId
WHERE aloc.id is not null or adbl.id is not null

注意:如果Area 中的多行匹配每一列,这将不起作用。但是,这似乎不太可能,因为匹配项位于名为 id 的列上。

【讨论】:

    【解决方案2】:

    或者在加入时通常很慢
    查询优化器进入循环连接

    JOIN Area AS area 
      ON Area.Id = psaLocalityOrCity.AreaId 
      OR Area.Id = psaDbl.AreaId
    

    不一样现在你有两个区域要处理
    但你知道该地区来自哪里
    可能会导致更多行但会更快
    Linoff 的答案更好

    LEFT JOIN Area AS AreaCity 
      ON AreaCity.Id = psaLocalityOrCity.AreaId 
    LEFT JOIN Area AS AreaDpl 
      ON AreaDpl.Id  = psaDbl.AreaId
    

    【讨论】:

      【解决方案3】:

      有一些方法可以提高此类查询的性能。(但我不确定它是否适合您。)

      可以采取以下措施来提高性能:

      1. 在所有表中使用 WITH (NOLOCK)
      2. 如果您每天多次使用查询,请尝试创建缓存表,即将结果填充到表中并使用 select 语句始终从表中检索结果。
      3. 在 select 语句中只放入需要的列。

      【讨论】:

      • 使用 nolock 有时是可取的,但如果使用太频繁可能会被视为不好的做法。大多数情况下,它是针对症状的补丁解决方案,并隐藏了真正的问题
      • 值得一试。 :)
      【解决方案4】:

      抱歉,通过使用 SELECT 和 UNION 将 psaLocalityOrCity 和 psaDbl 合二为一解决了这个问题。这使我能够从 INNER JOIN 中消除 OR 并且查询现在执行得更好。从这里得到想法: Is having an 'OR' in an INNER JOIN condition a bad idea?

      感谢您的所有建议

      【讨论】:

        猜你喜欢
        • 2011-10-04
        • 1970-01-01
        • 2013-10-15
        • 2017-04-24
        • 2017-12-24
        • 2016-08-28
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        相关资源
        最近更新 更多