Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 运行查询时确保冷缓存_Sql_Sql Server - Fatal编程技术网

Sql 运行查询时确保冷缓存

Sql 运行查询时确保冷缓存,sql,sql-server,Sql,Sql Server,是否有一个提示可用于确保在运行特定查询时优化器不会使用缓存查询计划 我已经找到了强制使用特定计划的方法,但我要求的是相反的方法。我尝试添加以下提示: 选项(不使用计划) 或者我需要实际清除部分缓存吗?对于单个查询,您可以使用选项“重新编译”在每次执行时强制执行新计划。可能是这样的: SELECT T.Column1, T2.Column2 FROM T INNER JOIN T2 ON T.ID = T2.ID WHERE T.Column2

是否有一个提示可用于确保在运行特定查询时优化器不会使用缓存查询计划

我已经找到了强制使用特定计划的方法,但我要求的是相反的方法。我尝试添加以下提示:

选项(不使用计划)


或者我需要实际清除部分缓存吗?

对于单个查询,您可以使用
选项“重新编译”
在每次执行时强制执行新计划。可能是这样的:

SELECT  T.Column1, T2.Column2
FROM    T
        INNER JOIN T2
            ON T.ID = T2.ID
WHERE   T.Column2 = @SomeParameter
OPTION (RECOMPILE);
或者在存储过程级别上,您可以使用:

如果您希望将存储过程标记为不进行重新编译(即,下次运行缓存计划时不要使用它),您可以使用:


我没有意识到Martin Smith提到的复杂性,我尝试重新创建它们,但无法(尽管我一点也不怀疑他,我只是觉得我的测试场景太简单了),但是,我想我还是要添加结果

我创建了这个模式:

IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
        DROP TABLE dbo.T;
GO
CREATE TABLE dbo.T 
(   ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
    Column1 INT NOT NULL, 
    Column2 INT NULL
);
INSERT dbo.T (Column1, Column2)
SELECT  TOP 9999 1, Number
FROM    Master..spt_values
UNION ALL
SELECT  TOP 1001 Number, Number
FROM    Master..spt_values
WHERE   Type ='P';

CREATE NONCLUSTERED INDEX IX_T_Column1 ON dbo.T (Column1 ASC);
故意对表进行加权,以便选择其中的
column1=1
应使用聚集索引扫描,但所有其他条件应使用非聚集索引。对照病例为:

DBCC FREEPROCCACHE;
DECLARE @SQL NVARCHAR(MAX) = 'SELECT COUNT(T.Column2) FROM dbo.T WHERE T.Column1 = @ID';
DECLARE @ParamDef NVARCHAR(MAX) =  N'@ID INT';

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 1;
EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;
产生了两个相同的计划:

下一个场景是向查询添加
选项(重新编译)

DBCC FREEPROCCACHE;
DECLARE @SQL NVARCHAR(MAX) = '  SELECT  COUNT(T.Column2) 
                                FROM    dbo.T 
                                WHERE   T.Column1 = @ID 
                                OPTION (RECOMPILE);';

DECLARE @ParamDef NVARCHAR(MAX) =  N'@ID INT';

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 1;
EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;
这将为@ID=1提供与前两个相同的执行计划,但现在为@ID=2使用书签查找,这是检索单行时更有效的计划

注意:如果我先用@ID=2执行,没有重新编译,两个计划仍然是相同的,但都会使用上面显示的@ID=2的键查找

另一个替代
选项(重新编译)
的选项是清除特定查询的缓存:

DBCC FREEPROCCACHE;
DECLARE @SQL NVARCHAR(MAX) = '  SELECT  COUNT(T.Column2)
                                FROM    dbo.T 
                                WHERE   T.Column1 = @ID';
DECLARE @ParamDef NVARCHAR(MAX) =  N'@ID INT';

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 1;
EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;

DECLARE @PlanHandle VARBINARY(64) = 
                    (   SELECT  TOP 1 PLAN_HANDLE
                        FROM    SYS.DM_EXEC_CACHED_PLANS
                                CROSS APPLY SYS.DM_EXEC_SQL_TEXT(PLAN_HANDLE) AS ST
                        WHERE   ST.TEXT = '(' + @ParamDef + ')' + @SQL
                    );

DBCC FREEPROCCACHE (@PlanHandle);

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;

最初(与控制案例一样),所有参数值都使用相同的计划,但是,您可以清除特定查询定义的缓存,一旦完成,键查找计划将用于@ID=2


因此,如果
选项(重新编译)
未按预期工作,则可以使用查询文本的计划句柄清除该特定查询的缓存。

是否考虑过
选项(重新编译)
在语句级或
在存储过程级使用RECOMPILE
选项RECOMPILE
不一定会提供与没有冷缓存提示时相同的计划。当SQL Server知道计划不会被重用时,它可以做更多的简化@我正在对我们的生产数据库运行这些查询,所以不可能为冷缓存清除内容,是吗。。。。我需要从缓存中删除特定的计划?@whytheq
DBCC FREEPROCCACHE
接受特定计划的句柄(对于2008年+),顺便说一句,简化的一个例子是在对可选参数使用
时,其中@param为NULL或@param=col
模式。需要2008+感谢Gareth的全面回答-我会在以后给出所有这些
DBCC FREEPROCCACHE;
DECLARE @SQL NVARCHAR(MAX) = '  SELECT  COUNT(T.Column2) 
                                FROM    dbo.T 
                                WHERE   T.Column1 = @ID 
                                OPTION (RECOMPILE);';

DECLARE @ParamDef NVARCHAR(MAX) =  N'@ID INT';

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 1;
EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;
DBCC FREEPROCCACHE;
DECLARE @SQL NVARCHAR(MAX) = '  SELECT  COUNT(T.Column2)
                                FROM    dbo.T 
                                WHERE   T.Column1 = @ID';
DECLARE @ParamDef NVARCHAR(MAX) =  N'@ID INT';

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 1;
EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;

DECLARE @PlanHandle VARBINARY(64) = 
                    (   SELECT  TOP 1 PLAN_HANDLE
                        FROM    SYS.DM_EXEC_CACHED_PLANS
                                CROSS APPLY SYS.DM_EXEC_SQL_TEXT(PLAN_HANDLE) AS ST
                        WHERE   ST.TEXT = '(' + @ParamDef + ')' + @SQL
                    );

DBCC FREEPROCCACHE (@PlanHandle);

EXECUTE SP_EXECUTESQL @SQL, @ParamDef, @ID = 2;