2017-06-07 16 views
4

SQL Server 2012 SP3 Enterprise Editionで、アプリケーションによって実行される特定のクエリに対してプランガイドを作成しようとしています。エイリアスを使用しないでプランガイドを作成する

クエリは次のようになります。プランガイドを作成するには

(@P1 nvarchar(5),@P2 bigint) 
DELETE FROM INVENTSUMDELTA WHERE (([email protected]) AND ([email protected])) 

、私は次のクエリを使用:

EXEC sp_create_plan_guide 
@name = N'INVENTSUMDELTAINDEX', 
@stmt = N'DELETE FROM INVENTSUMDELTA WHERE (([email protected]) AND ([email protected]))',  
@type = N'SQL', 
@module_or_batch = NULL, 
@params = N'@P1 nvarchar(5),@P2 bigint', 
@hints = N'OPTION (TABLE HINT (INVENTSUMDELTA, INDEX(I_2397TTSDIMIDX)))'; 

はしかし、私はエラーを受け取っ:

Msg 8724, Level 16, State 1, Line 1 Cannot execute query. Table-valued or OPENROWSET function 'INVENTSUMDELTA' cannot be specified in the TABLE HINT clause.

私は文書をチェックし、以下を見つけました:

TABLE HINT (exposed_object_name [ , [ [, ]...n ] ]) Applies the specified table hint to the table or view that corresponds to exposed_object_name. [...]

exposed_object_name can be one of the following references:

  • When an alias is used for the table or view in the FROM clause of the query, exposed_object_name is the alias.

  • When an alias is not used, exposed_object_name is the exact match of the table or view referenced in the FROM clause. For example, if the table or view is referenced using a two-part name, exposed_object_name is the same two-part name.

ここから、エイリアスを使用していないクエリのプランガイドを作成することが可能であることがわかっています。しかし、私はそれを働かせることはできません。

私の質問は、エイリアシングを使用せずに元のクエリを変更せずにプランガイドを作成する方法です。

+0

テーブルがあり(dboスキーマ内にあります)、UDFはありません。 – Monzie

答えて

2

エラーメッセージは誤解を招く可能性があります。オブジェクトの性質とは関係ありません(存在しないオブジェクトで同じエラーが発生します)。問題は、DELETEステートメントでは機能しないことです.DELETEの対象となるテーブルを参照するTABLE HINTはこのエラーを生成します。これは、どちらかのガイドを計画するために制限されない - オプション付きDELETEプレーンも同様に失敗します:

DELETE FROM does_not_exist 
OPTION (TABLE HINT (does_not_exist, INDEX (does_not_exist))) 
これは、バグのように見える

Cannot execute query. Table-valued or OPENROWSET function 'does_not_exist' cannot be specified in the TABLE HINT clause.

文は両方でWITH (ROWLOCK)ヒントで増強されている場合ので、

DELETE FROM does_not_exist WITH (ROWLOCK) 
OPTION (TABLE HINT (does_not_exist, ROWLOCK, INDEX (does_not_exist))) 

Invalid object name 'does_not_exist'.

同じ問題がthis questionに覆われ、その溶液は、QUを書き換えることである:テーブル、クエリのレベルは、エラーが消えますヒントを適用することが可能な形式でエリー。

このケースでは、クエリを直接書き換えることはできませんが、我々はまだfixed query plan guideを使用して、所望の効果を得ることができます:いつものように

-- Alternate query using hint. 
DECLARE @sql NVARCHAR(MAX) = N'WITH T AS (
    SELECT * 
    FROM INVENTSUMDELTA WITH (INDEX (I_2397TTSDIMIDX)) 
    WHERE (([email protected]) AND ([email protected])) 
) 
DELETE T'; 
DECLARE @params NVARCHAR(MAX) = N'@P1 nvarchar(5),@P2 bigint' 

-- Put the execution plan in the cache. 
EXEC sp_executesql @sql, @params = @params, @P1=NULL, @P2=NULL; 

-- Retrieve it. 
DECLARE @query_plan NVARCHAR(MAX); 
SELECT @query_plan = query_plan 
FROM sys.dm_exec_query_stats AS qs 
CROSS APPLY sys.dm_exec_sql_text(qs.[sql_handle]) AS st 
CROSS APPLY sys.dm_exec_text_query_plan(qs.[plan_handle], DEFAULT, DEFAULT) AS qp 
WHERE st.[text] LIKE '(' + @params + ')%' + @sql; 

-- Create a plan guide associating the query with the new execution plan. 
EXEC sp_create_plan_guide 
    @name = N'INVENTSUMDELTAINDEX', 
    @stmt = N'DELETE FROM INVENTSUMDELTA WHERE (([email protected]) AND ([email protected]))',  
    @type = N'SQL', 
    @module_or_batch = NULL, 
    @params = @params, 
    @hints = @query_plan; 

を何もない場合は、プランガイドは、最後の手段でなければなりません統計の更新、新しい索引の作成、準最適な索引の削除を支援します。この回答は、他のすべてのオプションを確認した上で、プランガイドが必要であることを前提としています。

+0

あなたの答えをありがとう!私はそれが適切なFROM節を欠いているDELETEと何か関係があると考えましたが、この回避策は考えていませんでした。私は来週まで解決策を試すことができないので、それまで受け入れられているとマークすることで待ちます。 – Monzie

+0

@ Monzie:2つ目のインデックスを作成し、プランガイドとの間の実行計画をオンとオフにして比較することで動作することを確認しました。そのため、状況に応じて動作しない場合は、必ず詳細を追加してください。特に、クエリテキストとパラメータ化を一致させることは、プランガイドを使用するのが難しい場合があります。 –

+0

@Monzie:もう1つ - 実行計画に渡されたパラメータによる行見積もりが反映されているかどうかはわかりません。そうであれば、実際に行を削除しないようにするためにロールバックされたトランザクションの中で、実行時に代表的なパラメータ値を渡す必要があるかもしれませんし、 'OPTIMIZE FOR'ヒントを使って代表値を提供することもできます。これは、ちょうどヒントを持つガイドとは対照的に、固定クエリプランを使用した場合の悪影響です。 'OPTIMIZE FOR'自体がインデックスの使用を可能にし、この固定クエリ全体を不要にすることに注意してください。 –

関連する問題