标签:apply arc substr 行数据 evel led address sam row
本文属于《理解性能的奥秘——应用程序中慢,SSMS中快》系列
接上文:理解性能的奥秘——应用程序中慢,SSMS中快(3)——不总是参数嗅探的错
前面已经提到过关于存储过程在SSMS中运行很快,但在应用程序中运行很慢的可能原因:因为ARITHABORT的不同选项会导致不同的缓存词目,另外由于SQL Server使用了参数嗅探导致获得了不同的执行计划。
虽然已经说明了这个现象的原因,但是还没解释:如何定位和解决这个问题?到目前为止,大家都知道了如何快速处理,如果这个问题很紧急,可以直接使用:
EXEC sp_recompile 存储过程名
前面提到过,这个操作会刷新计划缓存。下次存储过程被调用时,会产生新的查询计划。如果通过这种方式可以解决,那么认为这个已经不是问题了。
但是如果问题依旧,那么就需要做更深入的研究,并且不适合再用sp_recompile或者类似的方式去修改存储过程。另外请一直打开显示执行计划的选项以便用于对比和检查,最起码可以获取参数的值(可以通过右键执行计划→【显示执行计划XML】的方式在XML格式的执行计划中搜索ParameterList的值)。这是本节的主题。
在开始本节之前,给个小建议:修改SSMS的默认值,以便因为ARITHABORT的默认值带来困惑。建议把这个值设为OFF。但是与应用程序相同设置确实会有一些小缺点:你可能观察不到与参数嗅探有关的性能问题。但是如果你已经养成了都校验ARITHABORT ON和OFF的结果,那么这个问题就不成问题了。
SET ARITHABORT ON go EXEC that_very_sp 4711, 123, 1 go SET ARITHABORT OFF go EXEC that_very_sp 4711, 123, 1
DECLARE @dbname NVARCHAR(256), @procname NVARCHAR(256) SELECT @dbname = ‘Northwind‘, @procname = ‘dbo.List_orders_11‘; WITH basedata AS ( SELECT qs.statement_start_offset / 2 AS stmt_start, qs.statement_end_offset / 2 AS stmt_end, est.encrypted AS isencrypted, est.TEXT AS sqltext, epa.value AS set_options, qp.query_plan, charindex(‘<ParameterList>‘, qp.query_plan) + len(‘<ParameterList>‘) AS paramstart, charindex(‘</ParameterList>‘, qp.query_plan) AS paramend FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) est CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) qp CROSS APPLY sys.dm_exec_plan_attributes(qs.plan_handle) epa WHERE est.objectid = object_id(@procname) AND est.dbid = db_id(@dbname) AND epa.attribute = ‘set_options‘ ), next_level AS ( SELECT stmt_start, set_options, query_plan, CASE WHEN isencrypted = 1 THEN ‘-- ENCRYPTED‘ WHEN stmt_start >= 0 THEN substring(sqltext, stmt_start + 1, CASE stmt_end WHEN 0 THEN datalength(sqltext) ELSE stmt_end - stmt_start + 1 END) END AS Statement, CASE WHEN paramend > paramstart THEN CAST(substring(query_plan, paramstart, paramend - paramstart) AS XML) END AS params FROM basedata ) SELECT set_options AS [SET], n.stmt_start AS Pos, n.Statement, CR.c.value(‘@Column‘, ‘nvarchar(128)‘) AS Parameter, CR.c.value(‘@ParameterCompiledValue‘, ‘nvarchar(128)‘) AS [Sniffed Value], CAST(query_plan AS XML) AS [Query plan] FROM next_level n CROSS APPLY n.params.nodes(‘ColumnReference‘) AS CR(c) ORDER BY n.set_options, n.stmt_start, Parameter
USE Northwind GO CREATE PROCEDURE List_orders_11 @fromdate DATETIME, @custid NCHAR(5) AS SELECT @fromdate = dateadd(YEAR, 2, @fromdate) SELECT * FROM Orders WHERE OrderDate > @fromdate AND CustomerID = @custid IF @custid = ‘ALFKI‘ CREATE INDEX test ON Orders (ShipVia) SELECT * FROM Orders WHERE CustomerID = @custid AND OrderDate > @fromdate IF @custid = ‘ALFKI‘ DROP INDEX test ON Orders GO SET ARITHABORT ON EXEC List_orders_11 ‘19980101‘, ‘ALFKI‘ GO SET ARITHABORT OFF EXEC List_orders_11 ‘19970101‘, ‘BERGS‘
DECLARE @tbl NVARCHAR(265) SELECT @tbl = ‘Orders‘ SELECT o.NAME, i.index_id, i.NAME, i.type_desc, substring(ikey.cols, 3, len(ikey.cols)) AS key_cols, substring(inc.cols, 3, len(inc.cols)) AS included_cols, stats_date(o.object_id, i.index_id) AS stats_date, i.filter_definition FROM sys.objects o JOIN sys.indexes i ON i.object_id = o.object_id CROSS APPLY ( SELECT ‘, ‘ + c.NAME + CASE ic.is_descending_key WHEN 1 THEN ‘ DESC‘ ELSE ‘‘ END FROM sys.index_columns ic JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 ORDER BY ic.key_ordinal FOR XML PATH(‘‘) ) AS ikey(cols) OUTER APPLY ( SELECT ‘, ‘ + c.NAME FROM sys.index_columns ic JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 1 ORDER BY ic.index_column_id FOR XML PATH(‘‘) ) AS inc(cols) WHERE o.NAME = @tbl AND i.type IN ( 1, 2 ) ORDER BY o.NAME, i.index_id
DECLARE @tbl NVARCHAR(265) SELECT @tbl = ‘Orders‘ SELECT o.NAME, s.stats_id, s.NAME, s.auto_created, s.user_created, substring(scols.cols, 3, len(scols.cols)) AS stat_cols, stats_date(o.object_id, s.stats_id) AS stats_date, s.filter_definition FROM sys.objects o JOIN sys.stats s ON s.object_id = o.object_id CROSS APPLY ( SELECT ‘, ‘ + c.NAME FROM sys.stats_columns sc JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id WHERE sc.object_id = s.object_id AND sc.stats_id = s.stats_id ORDER BY sc.stats_column_id FOR XML PATH(‘‘) ) AS scols(cols) WHERE o.NAME = @tbl ORDER BY o.NAME, s.stats_id
UPDATE STATISTICS 表名 WITH FULLSCAN, INDEX
UPDATE STATISTICS tbl indexname WITH FULLSCAN注意:在表名和索引名之间没有句号,只有空格。
DBCC SHOW_STATISTICS (Orders, OrderDate)
理解性能的奥秘——应用程序中慢,SSMS中快(4)——收集解决参数嗅探问题的信息
标签:apply arc substr 行数据 evel led address sam row
原文地址:http://blog.csdn.net/dba_huangzj/article/details/53208427