UAT和PROD都具有完全数据和索引.
查询:
set statistics io on; set statistics time on; SELECT CONF_NO,'DE','Duplicate Email Address ''' + RTRIM(EMAIL_ADDRESS) + ''' in Maintenance',CONF_TARGET_NO FROM CONF_TARGET ct WHERE CONF_NO = 161 AND LEFT(INTERNET_USER_ID,6) != 'ICONF-' AND ( ( REGISTRATION_TYPE = 'I' AND (SELECT COUNT(1) FROM PORTFOLIO WHERE EMAIL_ADDRESS = ct.EMAIL_ADDRESS AND DEACTIVATED_YN = 'N') > 1 ) OR ( REGISTRATION_TYPE = 'K' AND (SELECT COUNT(1) FROM CAPITAL_MARKET WHERE EMAIL_ADDRESS = ct.EMAIL_ADDRESS AND DEACTIVATED_YN = 'N') > 1 ) )
在UAT上:
sql Server parse and compile time: cpu time = 0 ms,elapsed time = 0 ms. sql Server Execution Times: cpu time = 0 ms,elapsed time = 0 ms. sql Server parse and compile time: cpu time = 11 ms,elapsed time = 11 ms. sql Server Execution Times: cpu time = 0 ms,elapsed time = 0 ms. (3 row(s) affected) Table 'Worktable'. Scan count 256,logical reads 1304616,physical reads 0,read-ahead reads 0,lob logical reads 0,lob physical reads 0,lob read-ahead reads 0. Table 'PORTFOLIO'. Scan count 1,logical reads 84761,lob read-ahead reads 0. Table 'CAPITAL_MARKET'. Scan count 256,logical reads 9472,lob read-ahead reads 0. Table 'CONF_TARGET'. Scan count 1,logical reads 100,lob read-ahead reads 0. (1 row(s) affected) sql Server Execution Times: cpu time = 2418 ms,elapsed time = 2442 ms. sql Server parse and compile time: cpu time = 0 ms,elapsed time = 0 ms.
关于PROD:
sql Server parse and compile time: cpu time = 0 ms,elapsed time = 0 ms. sql Server parse and compile time: cpu time = 0 ms,elapsed time = 0 ms. (3 row(s) affected) Table 'PORTFOLIO'. Scan count 256,logical reads 21698816,lob read-ahead reads 0. (1 row(s) affected) sql Server Execution Times: cpu time = 23937 ms,elapsed time = 23935 ms. sql Server parse and compile time: cpu time = 0 ms,elapsed time = 0 ms.
请注意,在PROD上,查询建议缺少索引,这在我测试时是有益的,但这不是讨论的重点.
我只想了解:
ON UAT – 为什么sql server创建一个worker表而在PROD上却没有?它在UAT上而不是在PROD上创建一个表盘.另外,为什么UAT和PROD的执行时间如此不同?
注意 :
我在两台服务器上运行sql server 2008 R2 RTM(很快就要用最新的SP补丁).
UAT:最大内存8GB. MaxDop,处理器关联和最大工作线程为0.
Logical to Physical Processor Map: *------- Physical Processor 0 -*------ Physical Processor 1 --*----- Physical Processor 2 ---*---- Physical Processor 3 ----*--- Physical Processor 4 -----*-- Physical Processor 5 ------*- Physical Processor 6 -------* Physical Processor 7 Logical Processor to Socket Map: ****---- Socket 0 ----**** Socket 1 Logical Processor to NUMA Node Map: ******** NUMA Node 0
PROD:最大内存60GB. MaxDop,处理器关联和最大工作线程为0.
Logical to Physical Processor Map: **-------------- Physical Processor 0 (Hyperthreaded) --**------------ Physical Processor 1 (Hyperthreaded) ----**---------- Physical Processor 2 (Hyperthreaded) ------**-------- Physical Processor 3 (Hyperthreaded) --------**------ Physical Processor 4 (Hyperthreaded) ----------**---- Physical Processor 5 (Hyperthreaded) ------------**-- Physical Processor 6 (Hyperthreaded) --------------** Physical Processor 7 (Hyperthreaded) Logical Processor to Socket Map: ********-------- Socket 0 --------******** Socket 1 Logical Processor to NUMA Node Map: ********-------- NUMA Node 0 --------******** NUMA Node 1
更新:
UAT执行计划XML:
PROD执行计划XML:
UAT执行计划XML – 从PROD生成计划:
服务器配置:
PROD:PowerEdge R720xd – Intel(R)Xeon(R)cpu E5-2637 v2 @ 3.50GHz.
UAT:PowerEdge 2950 – Intel(R)Xeon(R)cpu X5460 @ 3.16GHz
我发布于answers.sqlperformance.com
更新:
感谢@swasheck的建议
将PROD上的最大内存从60GB更改为7680 MB,我可以在PROD中生成相同的计划.查询与UAT同时完成.
现在我需要明白 – 为什么?另外,通过这个,我无法证明这个怪物服务器能够取代旧服务器!
解决方法
工作区内存
对于包含内存消耗迭代器(如排序和散列)的计划,缓冲池的大小(以及其他内容)确定查询在运行时可用的最大内存授予量.
在sql Server 2012(所有版本)中,此数字在查询计划的根节点上报告,在Optimizer Hardware Dependencies部分中显示为Estimated Available Memory Grant. 2012年之前的版本不会在展示计划中报告此数字.
估计的可用内存授予是查询优化器使用的成本模型的输入.因此,在具有较大缓冲池设置的计算机上比在具有较低设置的计算机上更可能选择需要大型排序或散列操作的计划备选方案.对于具有大量内存的安装,成本模型可能会因为这种想法而走得太远 – 选择具有非常大的排序或散列的计划,其中替代策略将是更可取的(KB2413549 – Using large amounts of memory can result in an inefficient plan in SQL Server – TF2335).
工作区内存授权不是您的案例中的一个因素,但它值得了解.
数据访问
缓冲池的潜在大小也会影响优化程序的数据访问成本模型.模型中的一个假设是每个查询都以冷缓存开始 – 因此首先访问页面会产生物理I / O.该模型确实试图考虑重复访问将来自缓存的可能性,该因素取决于缓冲池的潜在大小等.
问题中显示的查询计划中的聚集索引扫描是重复访问的一个示例;对于嵌套循环半连接的每次迭代,扫描被重绕(重复,没有相关参数的改变).半连接的外部输入估计28.7874行,并且这些扫描的查询计划属性显示估计的倒带为27.7874.
同样,仅在sql Server 2012中,计划的根迭代器显示优化器硬件依赖关系部分中缓存的估计页数.此编号报告成本算法的一个输入,该算法旨在考虑重复页面访问来自缓存的可能性.
结果是,具有更高配置的最大缓冲池大小的安装将倾向于降低与具有较小最大缓冲池大小的安装相比读取相同页面的扫描(或搜索)的成本.
在简单的计划中,通过比较(估计的执行次数)*(估计的cpu估计的I / O)与估计的操作符成本,可以看到重绕扫描的成本降低.由于半连接和并集的影响,示例计划中的计算更复杂.
尽管如此,问题中的计划似乎表明,重复扫描和创建临时索引之间的选择非常精细.在具有较大缓冲池的计算机上,重复扫描的成本略低于创建索引.在具有较小缓冲池的计算机上,扫描成本减少了较少的量,这意味着索引假脱机计划看起来稍微便宜一点.
计划选择
优化器的成本模型做出了许多假设,并包含大量详细的计算.并不总是(或者甚至通常)可以遵循所有细节,因为并非所有我们需要的数字都会暴露,并且算法可以在不同版本之间进行更改.特别是,应用于考虑到遇到缓存页面的机会的缩放公式并不为人所知.
更重要的是,在这种特殊情况下,优化器的计划选择基于不正确的数字. Clustered Index Seek的估计行数为28.7874,而在运行时遇到256行 – 几乎是一个数量级.我们无法直接看到优化器关于28.7874行内值的预期分布的信息,但它也很可能是非常错误的.
当估计错误时,计划选择和运行时性能基本上不比偶然性好.具有索引假脱机的计划恰好比重复扫描更好,但认为增加缓冲池的大小是导致异常的原因是错误的.
在优化器具有正确信息的情况下,它将产生一个体面的执行计划的可能性要大得多.具有更多内存的实例通常比具有更少内存的另一个实例在工作负载上表现更好,但是没有保证,尤其是当计划选择基于不正确的数据时.
两个实例都以自己的方式建议缺少索引.一个报告显式缺失索引,另一个报告使用具有相同特征的索引假脱机.如果索引提供良好的性能和计划稳定性,那可能就足够了.我倾向于重写查询,但这可能是另一个故事.