特定のクエリを実行するときにオプティマイザがキャッシュされたクエリ プランを使用しないようにするためのヒントはありますか?
特定のプランの使用を強制するためのMSDN ページを見つけましたが、反対のプランが必要です。次のヒントを追加してみました。
OPTION (USE NO PLAN);
それとも、キャッシュの一部を実際にクリアする必要がありますか?
特定のクエリを実行するときにオプティマイザがキャッシュされたクエリ プランを使用しないようにするためのヒントはありますか?
特定のプランの使用を強制するためのMSDN ページを見つけましたが、反対のプランが必要です。次のヒントを追加してみました。
OPTION (USE NO PLAN);
それとも、キャッシュの一部を実際にクリアする必要がありますか?
個々のクエリでは、OPTION RECOMPILE
クエリ ヒントを使用して、実行ごとに新しいプランを強制できます。次のようになります。
SELECT T.Column1, T2.Column2
FROM T
INNER JOIN T2
ON T.ID = T2.ID
WHERE T.Column2 = @SomeParameter
OPTION (RECOMPILE);
または、ストアド プロシージャ レベルでWITH RECOMPILEを使用できます。
CREATE PROCEDURE dbo.TestRecompile @Param INT
WITH RECOMPILE
AS
SELECT *
FROM dbo.T;
一度だけ再コンパイルからストアド プロシージャをマークしたい場合 (つまり、次回の実行時にキャッシュされたプランを使用しない場合)、SP_RECOMPILEを使用できます。
EXECUTE sp_recompile 'dbo.ProcedureName';
私は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
select whereではクラスター化インデックス スキャンを使用する必要がありますが、他のすべての条件では非クラスター化インデックスを使用する必要があるため、意図的にテーブルに重みを付けます。コントロールケースは次のとおりです。
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;
これにより、2 つの同一の計画が作成されました。
次のシナリオはOPTION (RECOMPILE)
、クエリに追加することでした。
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 の最初の 2 つの実行プランと同じ実行プランが得られますが、@ID = 2 のブックマーク ルックアップが使用されます。これは、単一の行を取得するときにより効率的なプランです。
NB @ID = 2 で最初に再コンパイルせずに実行した場合、両方のプランは同じままですが、両方とも上記の @ID = 2 のキー ルックアップを使用します。
代わりの別のオプションOPTION (RECOMPILE)
は、特定のクエリのキャッシュをクリアすることです。
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 にキー ルックアップ プランが使用されます。
したがって、OPTION (RECOMPILE)
が期待どおりに機能しない場合は、クエリ テキストのプラン ハンドルを使用して、その特定のクエリのキャッシュをクリアできます。