比如:
SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
清除SQL缓存的方法:
清除查询计划缓存:
1 DBCC FREEPROCCACHE
2 清除某一数据库缓存:DBCC FLUSHPROCINDB (dbid) dbid获取方法:select db_id('northwind')
3 SQL系统自己清除缓存:
在下列情况下清除所有查询计划缓存:
-
Detaching any database.
-
Upgrading any database to SQL Server 2005 (on SQL Server 2005 server).
-
Running the DBCC FREEPROCCACHE command.
-
Running the ALTER DATABASE . . . MODIFY FILEGROUP command for any database.
-
Modifying a collation for any database using ALTER DATABASE . . . COLLATE command.
在下列情况下SQLServer清除某一数据库查询计划缓存
-
Running the DBCC FLUSHPROCINDB command.
-
Altering a database with any of the following options:
-
ALTER DATABASE . . . MODIFY NAME=command
-
ALTER DATABASE . . . SET ONLINE command
-
ALTER DATABASE . . . SET OFFLINE command
-
ALTER DATABASE . . . SET EMERGENCY command
-
-
When a database auto-closes
SQLServer查询计划重新编译:
手动重新编译查询计划:
调用系统存储过程sp_recompile 重新编译一个表或视图
数据库自动重新编译:
1 对象结构更新会引起查询计划重新编译,比如:
-
Adding or dropping columns to/from a table or view.
-
Adding or dropping constraints, defaults, or rules to or from a table.
-
Adding an index to a table or an indexed view.
-
Dropping an index defined on a table or an indexed view if the index is used by the plan.
-
Dropping a statistic defined on a table will cause a correctness-related recompilation of any query plans that use that table.
-
Adding or dropping a trigger from a table.
数据库确定以上行为是通过如下方法来确认的,查询
select modify_date from sys.objects where object_id = object_id('Employees')
确定日期是否更新过
2 调用 SET options引起查询计划重新编译
通过sys.dm_exec_plan_attributes函数可以查询该对象的SET options是否更改过
SELECT usecounts, cacheobjtype, objtype, [text],attr.*
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
CROSS APPLY sys.dm_exec_plan_attributes(plan_handle) as attr
WHERE cacheobjtype = 'Compiled Plan'
SELECT plan_handle, pvt.set_options, pvt.object_id, pvt.sql_handle
FROM (SELECT plan_handle, epa.attribute, epa.value
FROM sys.dm_exec_cached_plans
OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
WHERE cacheobjtype = 'Compiled Plan'
) AS ecpa
PIVOT (MAX(ecpa.value) FOR ecpa.attribute
IN ("set_options", "object_id", "sql_handle")) AS pvt;
获取对象属性值:
SELECT OBJECTPROPERTY(object_id('<object name>'), 'ExecIsQuotedIdentOn');
3 更新统计信息到一定阙值引起查询计划重新编译
手动更新统计信息:sp_updatestats or UPDATE STATISTICS command
自动更新统计信息:
当设置了set AUTO_UPDATE_STATISTICS on时系统会自动更新(sqlserver缺省设置)
当tablebe被确认为Stale Statistics状态时,系统会重新编译查询计划
每个table都有一个阙值称为RT,当他达到RT值时便认为table是Stale Statistics状态
RT在如下情况下会有相应的变化:
sql查询计划类型详解:
1 Adhoc Query Caching
当cacheobjtype是Compiled Plan 并且objtype为Adhoc,我们认为该查询计划为Adhoc Query Caching类型。该查询要求精确匹配时才能重用查询计划,也就是查询sql语句完全相等
比如:
USE Northwind;
go;
DBCC FREEPROCCACHE;
GO
SELECT * FROM Orders WHERE CustomerID = 'HANAR';
GO
SELECT * FROM Orders WHERE CustomerID = 'CHOPS';
GO
SELECT * FROM Orders WHERE CustomerID = 'HANAR';
GO
SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = 'Compiled Plan'
AND [text] NOT LIKE '%dm_exec_cached_plans%';
我们可以看到SELECT * FROM Orders WHERE CustomerID = 'HANAR';和SELECT * FROM Orders WHERE CustomerID = 'CHOPS'
是两个查询计划。另外如果sql存在大小写 空格、注释等等,sql也会把他们当做不同的查询计划。
因此,当你在程序开发中如果有大量的SQL查询时候,请不要如下使用
string sql = "SELECT * FROM Orders WHERE CustomerID = '"+customer+"'";
这样会产生大量的查询计划造成数据库内存占用过大,查询性能下降。
Autoparameterization
SQL Server can decide to treat one or more of the constants as parameters,这时候叫Autoparameterization
比如:
USE Northwind
GO
DBCC FREEPROCCACHE;
GO
SELECT FirstName, LastName, Title FROM Employees WHERE EmployeeID = 6;
GO
SELECT FirstName, LastName, Title FROM Employees WHERE EmployeeID = 2;
GO
SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = 'Compiled Plan'
AND [text] NOT LIKE '%dm_exec_cached_plans%';
GO
但是,sqlserver将查询计划作为Autoparameterization是十分谨慎的,上文因为EmployeeID 是聚集索引,所以返回的行数
肯定为1,但是当查询条件的索引为非聚集索引,那么返回的行数是不确定的,此时sqlserver将
不把他们作为Autoparameterization
另外sqlserver可以强制一个数据库查询将常量作为Autoparameterization类型,具体方法为:
ALTER DATABASE <database_name> SET PARAMETERIZATION FORCED;
The sp_executesql Procedure执行的sql也将查询计划设置为Autoparameterization类型
比如:
USE Northwind;
GO
SET STATISTICS IO ON;
GO
DBCC FREEPROCCACHE;
GO
EXEC sp_executesql N'SELECT * FROM Orders
WHERE CustomerID = @p', N'@p nvarchar(10)', 'CENTC';
GO
EXEC sp_executesql N'SELECT * FROM Orders
WHERE CustomerID = @p', N'@p nvarchar(10)', 'SAVEA';
GO
SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = 'Compiled Plan'
AND [text] NOT LIKE '%dm_exec_cached_plans%';
GO
SET STATISTICS IO OFF;
GO
Compiled Objects
Cacheobjtype是Compiled Plan Objtype是Proc的时候,认为是Compiled Objects,
存储过程,用户定义函数都属于该类型。
USE Northwind2;
GO
CREATE PROCEDURE P_Customers
@cust nvarchar(10)
AS
SELECT RowNum, CustomerID, OrderDate, ShipCountry
FROM BigOrders
WHERE CustomerID = @cust;
GO
DBCC FREEPROCCACHE;
GO
SET STATISTICS IO ON;
GO
EXEC P_Customers 'CENTC';
GO
EXEC P_Customers 'SAVEA';
GO
SELECT usecounts, cacheobjtype, objtype, [text]
FROM sys.dm_exec_cached_plans P
CROSS APPLY sys.dm_exec_sql_text (plan_handle)
WHERE cacheobjtype = 'Compiled Plan';
GO
EXEC P_Customers 'SAVEA' WITH RECOMPILE; 会使用新的查询计划并且不讲该计划缓存
几个有用的系统视图:
sys.dm_exec_sql_text
sql_handle or a plan_handle 作为他的参数 返回相应的SQL语句
USE Northwind;
DBCC FREEPROCCACHE;
SET QUOTED_IDENTIFIER OFF;
GO
--- this is an example of the relationship between
-- sql_handle and plan_handle
SELECT LastName, FirstName, Country
FROM Employees
WHERE Country <> 'USA';
GO
SET QUOTED_IDENTIFIER ON;
GO
--- this is an example of the relationship between
-- sql_handle and plan_handle
SELECT LastName, FirstName, Country
FROM Employees
WHERE Country <> 'USA';
GO
SELECT st.text, qs. sql_handle, qs.plan_handle
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) st;
GO
2 sys.dm_exec_cached_plan_dependent_objects
This DMF returns one row for every dependent object of a compiled plan when you pass a valid plan_handle in as a parameter
3 sys.dm_exec_requests
The sys.dm_exec_requests view returns one row for every currently executing request within your SQL Server instance
查询返回耗时前十的正在运行的SQL语句
SELECT TOP 10 SUBSTRING(text, (statement_start_offset/2) + 1,
((CASE statement_end_offset
WHEN -1
THEN DATALENGTH(text)
ELSE statement_end_offset
END - statement_start_offset)/2) + 1) AS query_text, *
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
ORDER BY total_elapsed_time DESC
4 sys.dm_exec_query_stats
返回平均耗时前十的SQL语句,从实例开始启动计算
SELECT TOP 10 SUBSTRING(text, (statement_start_offset/2) + 1,
((CASE statement_end_offset
WHEN -1
THEN DATALENGTH(text)
ELSE statement_end_offset
END - statement_start_offset)/2) + 1) AS query_text, *
FROM sys.dm_exec_query_stats
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
ORDER BY total_elapsed_time/execution_count DESC;