【问题标题】:Different execution plan from the same query in different SQL Server不同 SQL Server 中相同查询的不同执行计划
【发布时间】:2016-07-28 12:25:22
【问题描述】:

我对这个查询有一些疑问:

select distinct
    Date_Int,
    CodF,
    Desc_Com,
    DataDesc_Com,
    CodC,
    Function,
    Tratt_Number,
    Tratt_State
from 
    tmp_SIC_Trattative_Stato_com_l2

UNION 

SELECT DISTINCT
    case 
       when (ts.Date_Int is not null) 
          then ts.Date_Int 
          else All_Day.Date_Int 
    end as Date_Int,
    case 
       when (ts.CodF is not null) 
          then ts.CodF 
          else All_Day.CodF  
    end as CodF,
    case 
       when (ts.Desc_Com is not null) 
          then ts.Desc_Com 
          else All_Day.Desc_Com 
    end as Desc_Com,
    case 
       when (ts.DataDesc_Com is not null) 
          then ts.DataDesc_Com 
          else All_Day.DataDesc_Com 
    end as DataDesc_Com,
    case 
       when (ts.CodC is not null) 
          then ts.CodC 
          else All_Day.CodC 
    end as CodC,
    case when (ts.Function is not null) then ts.Function else All_Day.Function end as Function,
    case when (ts.Tratt_Number is not null) then ts.Tratt_Number else All_Day.Tratt_Number end as Tratt_Number,
    case when (ts.Tratt_State is not null) then ts.Tratt_State else All_Day.Tratt_State end as Tratt_State
FROM 
    Commerciali_All_Day as All_Day 
LEFT OUTER JOIN
    tmp_SIC_Trattative_Stato_com_l2 as ts ON ts.Date_Int = All_Day.Date_Int
                                          AND ts.CodF = All_Day.CodF
                                          AND ts.Desc_Com = All_Day.Desc_Com
                                          AND ts.DataDesc_Com = All_Day.DataDesc_Com
                                          AND ts.CodC = All_Day.CodC
                                          AND ts.Function = All_Day.Function
                                          AND ts.Tratt_State = All_Day.Tratt_State
WHERE 
    ts.Date_Int IS NULL

我在存储过程中执行此查询,但如果使用生产 SQL Server 或使用测试 SQL Server 执行存储过程,则执行计划会发生变化。

这是测试执行计划:

Test Execution Plan

这是生产执行计划:

Production Execution Plan

源表和存储过程在测试和生产中是一样的,我不明白,因为执行计划和时间不同。

在测试中,查询在 6 分钟内执行,在生产中在 15 分钟内执行。

测试和生产 SQL Server 是 Microsoft SQL Server 2014 版本 12.0.4100.1。

  • 生产服务器具有 24 GB RAM 和 8 CPU 2GHz
  • 测试服务器有 16 GB RAM 和 4 CPU 2GHz

我不明白为什么该程序在测试环境中执行得更好,而不是在生产环境中。

【问题讨论】:

  • 方案其实是一样的,费用是不一样的。如果您可以将计划提供为 XML,您可以获得更好的答案。具体来说,当您将鼠标悬停在排序和哈希匹配/连接上时,它将包括字段(可能相同)以及所涉及的记录数。
  • UNION 时不需要做SELECT DISTINCT,因为UNION 会删除所有重复项。 (UNION实际上是UNION DISTINCT的缩写。)
  • Test 和 Production 中的表格内容是否相同?表中的行数会影响计划。
  • 执行计划可能因服务器而异。这是数据库引擎针对给定查询(如果之前未缓存)的决定,以利用可用资源获得最佳性能。因此,如果资源不同,那么我们可以预期执行计划会有所不同。或者对于存储过程,如果参数集变化很大,那么对于第一次执行,缓存的执行计划最多不会执行其他参数集。
  • test和producton表是一样的:都是用同一个sql创建表,记录数也一样:Commerciali_All_Day是728.501行,tmp_SIC_Trattative_Stato_com_l2是22.539.465行

标签: sql sql-server stored-procedures query-optimization sql-server-2014


【解决方案1】:

问题的标题不是您真正想要的。您的产品和测试服务器之间有相同的查询计划。你真正要问的是为什么 prod 服务器比具有相同查询的测试服务器慢。

在 cmets 中,您回答 test 和 prod 之间的表格及其内容相同。具体来说,您提到它们具有相同的行数。

生产计划显示返回的数据多于测试计划。返回数据的最大兴趣点是 Commerciali_All_Day 上的表扫描,这是您对哈希表的构建输入。在测试中,它返回 725,858 行,总大小为 47MB。在 prod 中,它返回 728,941 行,总大小为 120MB。这是大小的两倍多,相差 3,083 行。

由于哈希构建输入表返回的数据量是其两倍以上,因此它在 prod 中比在 test 中大得多。在测试中,哈希表有 19,897,066 行,大小为 2,713MB。在 prod 中,哈希表是 20,006,362 行,大小为 4,732MB。 Prod 正在处理额外的 2GB 数据。

您需要返回并更好地查看 prod 和 test 中的数据之间的差异。在比较产品和测试计划时,您的所有表都没有返回相同数量的数据。这个查询的真正痛点是 Commerciali_All_Day 表。

【讨论】:

    【解决方案2】:

    您对问题标题的评论是正确的。最初生产和测试执行计划也是不同的,但是显式左外连接我获得了相同的执行计划,但执行时间不同。

    生产和测试之间存在不同的行数,因为测试的数据提前一天更新,因此没有 3,083 行。

    我检查了生产环境中处理的额外数据之间的差异,我发现了一个临时表,其中包含 2 个类型为 varchar(max) 的字段,在测试环境中为 varchar(25)。我更改了这两个字段的类型,现在执行时间和处理的数据是一样的。

    非常感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 2011-08-19
      • 1970-01-01
      • 2023-03-09
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多