使用联合时的性能问题

zwghvu4y  于 2022-10-03  发布在  其他
关注(0)|答案(1)|浏览(133)

目前我正在使用Union,这会导致]性能问题和运行时间较长的会话。我可以使用#temptable而不是Union吗?我已经编写了下面的查询,并使用了左连接。

SET NOCOUNT ON;  

     SELECT * FROM (   
        (SELECT DISTINCT si.num, si.code, 1 AS action_code  
          FROM stock si (NOLOCK)  
          LEFT OUTER JOIN product dpx (NOLOCK) ON si.owner_my_id = dpx.my_id  
          AND si.my_id = dpx.my_id  
          AND si.num = dpx.num  
          AND dpx.active_flag = 1  
          LEFT OUTER JOIN dp_page dpcx (NOLOCK) ON si.owner_my_id = dpcx.my_id   
          AND si.my_id = dpcx.my_id   
          AND si.num = dpcx.num   
          AND dpcx.active_flag = 1  
          LEFT OUTER JOIN dsi dsi (NOLOCK) ON si.owner_my_id = dsi.my_id  
          AND si.my_id = dsi.my_id  
          AND si.num = dsi.num  
          LEFT OUTER JOIN loadtable ilr (nolock)   
          ON si.my_id = ilr.my_id   
          AND si.num = ilr.num  
          AND getdate() between ilr.eff_date AND (end_date+1)  
          WHERE si.my_id = @my_id  
          AND si.owner_my_id = @my_id  
          AND (dpx.my_id IS NOT NULL OR dpcx.my_id IS NOT NULL OR dsi.my_id IS NOT NULL OR ilr.my_id IS NOT NULL) )  
          UNION  
          (SELECT DISTINCT dp.num, '-2' AS code, 0 AS action_code  
          FROM distributor_product dp (NOLOCK)  
          LEFT OUTER JOIN product dpx (NOLOCK) ON dp.my_id = dpx.my_id  
          AND dp.num = dpx.num  
          AND dpx.active_flag = 1  
          LEFT OUTER JOIN dp_page dpcx (NOLOCK) ON dp.my_id = dpcx.my_id   
          AND dp.num = dpcx.num   
          AND dpcx.active_flag = 1  
          LEFT OUTER JOIN dsi dsi (NOLOCK) ON dp.my_id = dsi.my_id  
          AND dp.num = dsi.num  
          LEFT OUTER JOIN loadtable ilr (nolock)   
          ON dp.my_id = ilr.my_id   
          AND dp.num = ilr.num  
          AND getdate() between ilr.eff_date AND (end_date+1)  
          WHERE dp.my_id = @my_id  
       AND (dpx.my_id IS NOT NULL OR dpcx.my_id IS NOT NULL OR dsi.my_id IS NOT NULL OR ilr.my_id IS NOT NULL)  
          ) ) a   

    END
n53p2ov0

n53p2ov01#

这是一个复杂的查询。一些优化肯定取决于您的各种表上的索引。你没跟我们说过这些。

这里有一些建议。

  • 使用UNION ALL代替UNIONUNION对结果集执行重复数据消除;对于较大的结果集,这可能非常耗时,因为重复数据消除需要进行数据洗牌和比较。它不会更改您的结果集。
  • 尽可能停止使用DISTINCT。与UNION ALL存在相同的性能问题。但从你的问题中还不清楚你是否可以停止使用DISTINCT
  • 排除此性能问题时,请删除NOLOCK限定符。无论如何,它们可能帮不了太大的忙。
  • 如果由于在运行此查询时出现死锁而必须使用NOLOCK语义,请在此查询之前使用SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;语句,而不是将NOLOCK隐藏在查询中。当您针对活动的事务性表执行历史报告时,有时会发生死锁。

但请注意,NOLOCK语义可能会生成虚假结果,特别是在事务数据库中主动更改行的情况下。尽可能避免使用LOCKREAD UNCOMMITTED。恕我直言,使用这些是草率的编程。

  • 通过与Union All的一个分支机构合作,然后与另一个分支机构合作,解决此性能问题。
  • 在SSMS中,右键单击查询(Union All的分支)并选择显示实际执行计划,然后运行查询,然后查看计划。有时,实际的执行计划会显示向某个表添加索引的建议。

如果这些建议对你没有帮助,请不要犹豫,再问一个问题。但如果你这样做,请..。

  • 只询问您的工会的一个分支机构,所有这些都会让事情变得更简单。
  • 显示所有涉及的表的表定义、索引和近似行数。
  • 使用Brent Ozar的Paste the Plan网络应用程序向我们展示实际的执行计划。

编辑可以使用内连接而不是左连接吗?

当您执行rightT LEFT JOIN leftT ON rightT.something = leftT.something时,您将从RIGRT获得所有行,即使是那些不符合ON条件的行。您的结果集包含缺少的Leftt列中的空值。

但是,如果您执行rightT INNER JOIN leftT ON rightT.something = leftT.something,则不会从RIGRT获得行,除非它们匹配ON条件。INTERNAL JOIN取消不匹配的行。

只有你才能回答关于为部分或全部查询的连接切换到内部连接的问题:你比‘toobz’(这就是我)上的某个rando更了解你的数据库设计。如果你仍然得到一个有用的结果集,其中包含被隐藏的不匹配的行,你可以切换。

相关问题