在过去4小时内重新创建了大多数查询计划


9

我的SQL Server数据库性能出现问题。我已经找到了此工具sp_BlitzCache。命令执行后,我得到以下语句:

您在过去24小时内创建了92.00%的计划,在过去4小时内创建了92.00%的计划。

在确定问题的同时(使用SQL Server Profiler,我检查了StmtRecompile事件的发生),但我只能找到一些经常被重建的全文本搜索查询。但是,全文搜索查询仅占所有查询的5%。

您有什么建议可能导致其余87%的计划重新生效吗?

我有SQL Server 2012(版本11.0.6567.0)。

编辑:我添加了我的性能计数器

+---------------------------+--------------------------------+--------------+
|        object_name        |          counter_name          |  cntr_value  |
+---------------------------+--------------------------------+--------------+
| SQLServer:Buffer Manager  | Background writer pages/sec    |            0 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio         |        28436 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio base    |        28436 |
| SQLServer:Buffer Manager  | Checkpoint pages/sec           |      8259452 |
| SQLServer:Buffer Manager  | Database pages                 |      4434337 |
| SQLServer:Buffer Manager  | Free list stalls/sec           |            9 |
| SQLServer:Buffer Manager  | Integral Controller Slope      |            0 |
| SQLServer:Buffer Manager  | Lazy writes/sec                |         5608 |
| SQLServer:Buffer Manager  | Page life expectancy           |       438901 |
| SQLServer:Buffer Manager  | Page lookups/sec               | 122694703703 |
| SQLServer:Buffer Manager  | Page reads/sec                 |     60994608 |
| SQLServer:Buffer Manager  | Page writes/sec                |    126076564 |
| SQLServer:Buffer Manager  | Readahead pages/sec            |     45305420 |
| SQLServer:Buffer Manager  | Target pages                   |    130990080 |
| SQLServer:Buffer Node     | Database pages                 |      4434337 |
| SQLServer:Buffer Node     | Page life expectancy           |       438901 |
| SQLServer:Buffer Node     | Local node page lookups/sec    |            0 |
| SQLServer:Buffer Node     | Remote node page lookups/sec   |            0 |
| SQLServer:Memory Manager  | External benefit of memory     |            0 |
| SQLServer:Memory Manager  | Connection Memory (KB)         |         3304 |
| SQLServer:Memory Manager  | Database Cache Memory (KB)     |     35474784 |
| SQLServer:Memory Manager  | Free Memory (KB)               |     13229808 |
| SQLServer:Memory Manager  | Granted Workspace Memory (KB)  |            0 |
| SQLServer:Memory Manager  | Lock Memory (KB)               |       455928 |
| SQLServer:Memory Manager  | Lock Blocks Allocated          |      1798154 |
| SQLServer:Memory Manager  | Lock Owner Blocks Allocated    |      3568588 |
| SQLServer:Memory Manager  | Lock Blocks                    |        10562 |
| SQLServer:Memory Manager  | Lock Owner Blocks              |        10617 |
| SQLServer:Memory Manager  | Maximum Workspace Memory (KB)  |     43368000 |
| SQLServer:Memory Manager  | Memory Grants Outstanding      |            0 |
| SQLServer:Memory Manager  | Memory Grants Pending          |            0 |
| SQLServer:Memory Manager  | Optimizer Memory (KB)          |         1400 |
| SQLServer:Memory Manager  | Reserved Server Memory (KB)    |            0 |
| SQLServer:Memory Manager  | SQL Cache Memory (KB)          |       229112 |
| SQLServer:Memory Manager  | Stolen Server Memory (KB)      |      8063232 |
| SQLServer:Memory Manager  | Log Pool Memory (KB)           |         4192 |
| SQLServer:Memory Manager  | Target Server Memory (KB)      |     56934400 |
| SQLServer:Memory Manager  | Total Server Memory (KB)       |     56767824 |
| SQLServer:Memory Node     | Database Node Memory (KB)      |     35474784 |
| SQLServer:Memory Node     | Free Node Memory (KB)          |     13229808 |
| SQLServer:Memory Node     | Foreign Node Memory (KB)       |            0 |
| SQLServer:Memory Node     | Stolen Node Memory (KB)        |      8063208 |
| SQLServer:Memory Node     | Target Node Memory (KB)        |     56934376 |
| SQLServer:Memory Node     | Total Node Memory (KB)         |     56767800 |
+---------------------------+--------------------------------+--------------+

也许有人运行了DBCC FREEPROCCACHE?:P
DanielBjörk17年

@DanielBjörk我是唯一有权执行此类操作的人,所以我认为这不是原因。但是,我会检查它。
Marcin Topolewski

您是否正在使用参数化查询或存储过程?还是您的SQL中包含字符串/数字文字,因此计划无法重复使用的问题?
James Z

@JamesZ是的,我正在使用很多参数化查询。我在帖子中提到的BlitzCache工具说我在参数嗅探方面遇到了问题。
Marcin Topolewski

1
您是每晚重建索引还是更新统计信息?服务器上可能存在内存压力?
埃里克·达林

Answers:


6

用于测试计划创建时间的查询是这个

WITH x AS (
SELECT SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 24 THEN 1 ELSE 0 END) AS [plans_24],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 4 THEN 1 ELSE 0 END) AS [plans_4],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 1 THEN 1 ELSE 0 END) AS [plans_1],
       COUNT(deqs.creation_time) AS [total_plans]
FROM sys.dm_exec_query_stats AS deqs
)
SELECT CONVERT(DECIMAL(3,2), NULLIF(x.plans_24, 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_24],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_4 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_4],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_1 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_1],
       @@SPID AS SPID
INTO #plan_creation
FROM x
OPTION (RECOMPILE) ;

SP还提供了一些线索,从何处开始您的进一步研究

如果这些百分比很高,则可能表示内存不足或计划缓存不稳定

除上述提示外,请检查服务器是否已重新启动。

如果您的服务器没有重新启动,那么下面是我会采用的方法

  • 检查您是否面对记忆压力

首先查看,如果您的内存设置配置最佳。如果是这样,则可以使用下面的计数器来查看您是否面临内存压力

内存:可用MB
SQL缓冲区:可用页面
SQL缓冲区:页面寿命
SQL缓冲区:延迟写入

如果您面临内存压力,则可以查看和调整正在使用更多内存的查询,或者尝试添加更多内存

您可能已经运行了导致重新编译的 查询。其中一些包括

  • 对查询所引用的表或视图的更改(ALTER TABLE和ALTER VIEW)。

  • 对单个过程进行的更改将导致从缓存中删除该过程的所有计划(ALTER PROCEDURE)。

  • 对执行计划使用的所有索引的更改

  • 执行计划使用的统计信息的更新,可以从一条语句(例如UPDATE STATISTICS)显式生成,也可以自动生成。

  • 删除执行计划使用的索引。

您还可以参阅此白皮书以了解有关计划缓存的更多详细信息

https://technet.microsoft.com/zh-CN/library/ee343986(v=sql.100).aspx


我添加了性能计数器,您能帮我解释一下这些价值吗?
Marcin Topolewski

你可以看出来详细的内存相关的计数器的位置:blogs.msdn.microsoft.com/teekamg/2007/11/06/...
TheGameiswar

@TheGameiswar,您说“您可能运行了会导致重新编译的查询...例如索引更改,统计信息更新”。如果我每晚都基于碎片+更新统计信息对索引进行重组/重建,这是否意味着我的计划将每天(或几乎全部)重新创建?那是问题吗?
丹尼尔·帕奎特·哈维

2

要添加@TheGameiswar所说的内容,您还可以运行此查询以查看未从缓存获取的计划的详细信息。

;with
    xmlnamespaces (N'http://schemas.microsoft.com/sqlserver/2004/07/showplan' as DYN)
select
    db_name(st.dbid) as DBName
    , object_schema_name(st.objectid, st.dbid) as SchemaName
    , object_name(st.objectid, st.dbid) as ObjectName
    , ecp.objtype
    , st.text
    , qp.query_plan.value('(/DYN:ShowPlanXML/DYN:BatchSequence/DYN:Batch/DYN:Statements/DYN:StmtSimple/@RetrievedFromCache)[1]', 'varchar(100)') as RetrievedFromCache
    , qp.query_plan
into #temp
from sys.dm_exec_cached_plans ecp
    outer apply sys.dm_exec_query_plan(ecp.plan_handle) qp
    outer apply sys.dm_exec_sql_text(ecp.plan_handle) st

select
    *
from #temp t
where t.RetrievedFromCache is null
    and t.DBName is not null
order by t.DBName, t.SchemaName, t.ObjectName;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.