クエリ ヒント (Transact-SQL)

クエリ ヒントは、指定されたヒントをクエリ全体で使用する必要があることを指定します。クエリ ヒントは、ステートメント内のすべての演算子に作用します。メイン クエリで UNION を使用する場合、UNION 操作を含む最後のクエリだけに OPTION 句を指定できます。クエリ ヒントは、OPTION 句の一部として指定します。複数のクエリ ヒントが原因でクエリ オプティマイザーが有効なプランを生成できない場合は、エラー 8622 が発生します。

注記注意

通常、クエリにとって最適な実行プランが SQL Server クエリ オプティマイザーによって選択されるため、ヒントは、経験を積んだ開発者やデータベース管理者が最後の手段としてのみ使用することをお勧めします。

適用対象

DELETE

INSERT

SELECT

UPDATE

MERGE

トピック リンク アイコンTransact-SQL 構文表記規則

構文

<query_hint > ::= 
{ { HASH | ORDER } GROUP 
  | { CONCAT | HASH | MERGE } UNION 
  | { LOOP | MERGE | HASH } JOIN 
  | FAST number_rows 
  | FORCE ORDER 
  | MAXDOP number_of_processors 
  | OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
  | OPTIMIZE FOR UNKNOWN
  | PARAMETERIZATION { SIMPLE | FORCED }
  | RECOMPILE
  | ROBUST PLAN 
  | KEEP PLAN 
  | KEEPFIXED PLAN
  | EXPAND VIEWS 
  | MAXRECURSION number 
  | USE PLAN N'xml_plan'| TABLE HINT ( exposed_object_name  [ , <table_hint> [ [, ]...n ] ] )<table_hint> ::=
[ NOEXPAND ] { 
    INDEX (index_value [ ,...n ] ) | INDEX = (index_value)
  | FASTFIRSTROW 
  | FORCESEEK
  | HOLDLOCK 
  | NOLOCK 
  | NOWAIT
  | PAGLOCK 
  | READCOMMITTED 
  | READCOMMITTEDLOCK 
  | READPAST 
  | READUNCOMMITTED 
  | REPEATABLEREAD 
  | ROWLOCK 
  | SERIALIZABLE 
  | TABLOCK 
  | TABLOCKX 
  | UPDLOCK 
  | XLOCK 
}

引数

  • { HASH | ORDER } GROUP
    クエリの GROUP BY 句、DISTINCT 句、または COMPUTE 句に記述されている集計でハッシュまたは順序付けを使用することを指定します。

  • { MERGE | HASH | CONCAT } UNION
    UNION セットをマージ、ハッシュ、または連結することによって、すべての UNION 操作を実行することを指定します。複数の UNION ヒントを指定した場合、クエリ オプティマイザーは指定されたヒントの中から最も負荷の軽い方法を選択します。

  • { LOOP | MERGE | HASH } JOIN
    LOOP JOIN、MERGE JOIN、または HASH JOIN によって、すべての結合操作がクエリ全体で実行されることを指定します。結合ヒントを複数指定した場合は、可能なヒントの中から最も負荷の軽い方法がオプティマイザーによって選択されます。

    同じクエリの中で、特定のテーブルのペアに対して FROM 句に結合ヒントが指定されている場合も、2 つのテーブルの結合ではこの結合ヒントが優先されますが、クエリ ヒントは引き続き有効です。このため、テーブルのペアの結合ヒントは、クエリ ヒント内で許可される結合方法の選択を制限できるだけです。詳細については、「結合ヒント (Transact-SQL)」を参照してください。

  • FAST number_rows
    最初の number_rows を高速検索するためにクエリの最適化を行うことを指定します。これは、負以外の整数です。最初の number_rows を返した後、クエリは実行を続け、完全な結果セットを作成します。

  • FORCE ORDER
    クエリの構文に示されている結合順序が、クエリの最適化中、保持されることを指定します。FORCE ORDER を使用しても、クエリ オプティマイザーのロールの逆引き動作に影響はありません。詳細については、「ハッシュ結合について」を参照してください。

    注意注意

    MERGE ステートメント内で、WHEN SOURCE NOT MATCHED 句が指定されていない限り、既定の結合順序としてソース テーブルはターゲット テーブルよりも前にアクセスされます。FORCE ORDER を指定すると、この既定の動作が維持されます。

    クエリにビューが含まれている場合の SQL Server クエリ オプティマイザーによる FORCE ORDER ヒントの設定については、「ビューの解決」を参照してください。

  • MAXDOP number
    このオプションを指定しているクエリに対して、sp_configure とリソース ガバナーの max degree of parallelism 構成オプションを上書きします。MAXDOP クエリ ヒントは、sp_configure で構成されている値を超えて指定できます。MAXDOP の値がリソース ガバナーで構成されている値を超える場合は、「ALTER WORKLOAD GROUP (Transact-SQL)」で説明されているように、データベース エンジンでリソース ガバナーの MAXDOP 値が使用されます。MAXDOP クエリ ヒントを使用している場合は、max degree of parallelism 構成オプションで使用されるすべてのセマンティック ルールを適用できます。詳細については、「max degree of parallelism オプション」を参照してください。

    注記注意

    MAXDOP が 0 に設定されている場合、サーバーで並列処理の最大限度が選択されます。サーバーは、DOP の上限を内部的に 64 に設定します。

  • OPTIMIZE FOR ( @variable\_name { UNKNOWN | = literal_constant } [ , ...n] )
    クエリをコンパイルおよび最適化するときにローカル変数に対して特定の値を使用するように、クエリ オプティマイザーに指示します。この値はクエリを最適化する過程でのみ使用され、クエリの実行時には使用されません。

    • @variable\_name
      クエリで使用されるローカル変数の名前です。このローカル変数に OPTIMIZE FOR クエリ ヒントで使用する値を割り当てます。

    • UNKNOWN
      クエリ オプティマイザーでのクエリの最適化時に、初期値の代わりに統計データを使用してローカル変数の値を決定することを指定します。

    • literal_constant
      OPTIMIZE FOR クエリ ヒントで使用する、@variable_name に割り当てるリテラル定数値です。literal_constant は、クエリの最適化の過程でのみ使用され、クエリの実行時に @variable\_name の値としては使用されません。literal_constant には、リテラル定数として表現できる任意の SQL Server システム データ型を指定できます。literal_constant のデータ型は、@variable_name がクエリ内で参照するデータ型に暗黙的に変換できる必要があります。

    OPTIMIZE FOR はオプティマイザーの既定のパラメーター検出動作を無効にする場合や、プラン ガイドを作成する場合に使用できます。詳細については、「ストアド プロシージャの再コンパイル」および「プラン ガイドを使用した配置済みアプリケーションのクエリの最適化」を参照してください。

  • OPTIMIZE FOR UNKNOWN
    クエリ オプティマイザーでクエリをコンパイルおよび最適化するときに、強制パラメーター化によって作成されたパラメーターも含め、すべてのローカル変数に対して初期値の代わりに統計データを使用することを指定します。強制パラメーター化の詳細については、「強制パラメータ化」を参照してください。

    同一のクエリ ヒント内で OPTIMIZE FOR @variable\_name = literal_constant と OPTIMIZE FOR UNKNOWN が使用されている場合、クエリ オプティマイザーでは、特定の値に対しては指定された literal_constant を使用し、残りの変数値には UNKNOWN を使用します。これらの値はクエリを最適化する過程でのみ使用され、クエリの実行時には使用されません。

  • PARAMETERIZATION { SIMPLE | FORCED }
    クエリのコンパイル時に SQL Server クエリ オプティマイザーがそのクエリに適用するパラメーター化のルールを指定します。

    重要な注意事項重要

    PARAMETERIZATION クエリ ヒントはプラン ガイド内部でのみ指定できます。クエリの中で直接指定することはできません。

    SIMPLE は、クエリ オプティマイザーに対して簡易パラメーター化を試行するように指示します。FORCED は、オプティマイザーに対して強制パラメーター化を試行するように指示します。PARAMETERIZATION クエリ ヒントは、プラン ガイド内部の PARAMETERIZATION データベース SET オプションの現在の設定を上書きするのに使用します。詳細については、「プラン ガイドを使用したクエリのパラメータ化動作の指定」を参照してください。

  • RECOMPILE
    クエリの実行後、そのクエリに対して生成されたプランを破棄し、次回同じクエリが実行されたときにクエリ オプティマイザーにクエリ プランを再コンパイルさせるよう SQL Server データベース エンジンに指示します。RECOMPILE を指定しない場合、データベース エンジンはクエリ プランをキャッシュして再利用します。クエリ プランをコンパイルする場合、RECOMPILE クエリ ヒントは、クエリ内のローカル変数の現在値を使用し、クエリがストアド プロシージャ内にある場合は任意のパラメーターに渡された現在値を使用します。

    RECOMPILE は、ストアド プロシージャ全体ではなくその中のクエリのサブセットだけを再コンパイルする必要がある場合に、WITH RECOMPILE 句を使用したストアド プロシージャを作成する代わりに使用すると便利です。詳細については、「ストアド プロシージャの再コンパイル」を参照してください。RECOMPILE はプラン ガイドを作成するときにも利用できます。詳細については、「プラン ガイドを使用した配置済みアプリケーションのクエリの最適化」を参照してください。

  • ROBUST PLAN
    クエリ オプティマイザーで、最大許容行サイズで動作するプランを試行するよう設定します。ただし、この場合は性能が低下する可能性があります。クエリの処理の際、中間テーブルや演算子が入力行よりも大きな行を格納し、処理しなければならない可能性があります。行があまりに大きいと、演算子によっては行を処理できない場合もあります。このような状態が発生すると、クエリの実行中にデータベース エンジンからエラーが出力されます。ROBUST PLAN を使用することで、クエリ オプティマイザーに対して、このような問題を発生するクエリ プランを考慮しないことを指示します。

    このようなプランが可能でない場合は、クエリ実行の後でエラー検出を行うのではなく、クエリ オプティマイザーがエラーを返します。行は可変長列で構成されている可能性があります。データベース エンジンでは、データベース エンジンが処理できる範囲を超えた最大可能サイズを持つように、行を定義できます。通常、可能な最大サイズに関係なく、アプリケーションはデータベース エンジンの処理能力で実際に対応できるサイズの行を格納します。データベース エンジンが長すぎる行を検出した場合は、実行エラーが返されます。

  • KEEP PLAN
    クエリ オプティマイザーに対して、クエリに推定される再コンパイルしきい値を緩和することを指定します。推定される再コンパイルしきい値とは、UPDATE、DELETE、MERGE、または INSERT ステートメントの実行により、予測した回数のインデックス列変更がテーブルに加えられた場合に、クエリを自動的に再コンパイルする時点のことです。KEEP PLAN を指定することによって、テーブルに複数の更新が加えられても、クエリは頻繁に再コンパイルされません。

  • KEEPFIXED PLAN
    統計情報の変更に応じてクエリを再コンパイルしないようにクエリ オプティマイザーを設定します。KEEPFIXED PLAN を指定することによって、クエリの基になるテーブルのスキーマが変更された場合、またはそのテーブルに対して sp_recompile が実行された場合のみ、クエリが再コンパイルされます。

  • EXPAND VIEWS
    インデックス付きビューが展開されていることを指定します。これによって、クエリ オプティマイザーがインデックス付きビューをクエリの一部の代わりであると見なすことがなくなります。ビューが展開されるのは、ビュー名がクエリ テキスト内のビュー定義に置換される場合です。

    このクエリ ヒントは、インデックス付きビューを直接使用することを実質的に禁止し、クエリ プラン内のインデックス付きビューにインデックスを指定します。

    クエリの SELECT 要素でビューが直接参照され、WITH (NOEXPAND) または WITH (NOEXPAND, INDEX( index_value [ ,...n ] ) ) が指定されている場合のみ、インデックス付きビューは展開されません。クエリ ヒント WITH (NOEXPAND) の詳細については、「FROM」を参照してください。

    INSERT、UPDATE、MERGE、DELETE ステートメントなど、ステートメントの SELECT 要素内のビューのみが、ヒントの影響を受けます。

  • MAXRECURSION number
    このクエリで許可される最大再帰数を指定します。number は、0 ~ 32,767 の負以外の整数です。0 を指定した場合、制限は適用されません。このオプションが指定されない場合、サーバーの既定の上限値である 100 が使用されます。

    クエリの実行中に MAXRECURSION の指定した上限値または既定上限値に達した場合、クエリは終了し、エラーが返されます。

    このエラーのため、ステートメントのすべての効果がロールバックされます。ステートメントが SELECT ステートメントであった場合、結果の一部が返されるか、結果がまったく返されないかのいずれかになります。結果の一部が返された場合でも、指定した最大再帰レベルを超える再帰レベルのすべての行は含まれていない可能性があります。

    詳細については、「WITH common_table_expression (Transact-SQL)」を参照してください。

  • USE PLAN N**'xml_plan'**
    'xml_plan' で指定されているクエリの既存のクエリ プランを使用するように、クエリ オプティマイザーを設定します。詳細については、「プラン強制の使用によるクエリ プランの指定」を参照してください。USE PLAN は、INSERT、UPDATE、MERGE、または DELETE の各ステートメントに指定することはできません。

  • TABLE HINT (exposed_object_name [ , <table_hint> [ [, ]...n] ] )
    指定されたテーブル ヒントを exposed_object_name に対応するテーブルまたはビューに適用します。プラン ガイドのコンテキスト内でのみ、テーブル ヒントをクエリ ヒントとして使用することをお勧めします。

    exposed_object_name には、次のいずれかの参照を指定できます。

    • クエリの FROM 句内でテーブルまたはビューに対して別名を使用する場合、exposed_object_name は別名です。

    • 別名を使用しない場合、exposed_object_name は、FROM 句で参照されているテーブルまたはビューと完全に一致している必要があります。たとえば、2 つの部分で構成される名前を使用してテーブルまたはビューが参照されている場合、exposed_object_name は、2 つの部分で構成される同じ名前です。

    テーブル ヒントを指定しないで exposed_object_name を指定した場合、オブジェクトのテーブル ヒントの一部としてクエリに指定された任意のインデックスは無視され、インデックスの使用はクエリ オプティマイザーによって決定されます。この手法を使用すると、元のクエリに変更を加えることができない場合に INDEX テーブル ヒントの効果を除去できます。例 J を参照してください。

  • <table_hint> ::= { [ NOEXPAND ] { INDEX ( index_value [ ,...n ] ) | INDEX = ( index_value ) | FASTFIRSTROW | FORCESEEK | HOLDLOCK | NOLOCK | NOWAIT | PAGLOCK | READCOMMITTED | READCOMMITTEDLOCK | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | TABLOCK | TABLOCKX | UPDLOCK | XLOCK }
    exposed_object_name に対応するテーブルまたはビューにクエリ ヒントとして適用するテーブル ヒントを指定します。これらのヒントの説明については、「テーブル ヒント (Transact-SQL)」を参照してください。

    INDEX および FORCESEEK 以外のテーブル ヒントは、クエリで既に WITH 句を使用してテーブル ヒントが指定されていない限り、クエリ ヒントとして使用できません。詳細については、「解説」を参照してください。

説明

ステートメント内部で SELECT 句が使用されている場合を除き、クエリ ヒントは INSERT ステートメントでは指定できません。

クエリ ヒントはサブクエリではなく、トップ レベルのクエリでのみ指定できます。テーブル ヒントをクエリ ヒントとして指定する場合、最上位レベルのクエリまたはサブクエリ内にヒントを指定できます。ただし、TABLE HINT 句の exposed_object_name に対して指定する値は、クエリまたはサブクエリ内で公開された名前と完全に一致する必要があります。

クエリ ヒントとしてのテーブル ヒントの指定

プラン ガイドのコンテキスト内でのみ、INDEX または FORCESEEK テーブル ヒントをクエリ ヒントとして使用することをお勧めします。プラン ガイドは、たとえばクエリがサードパーティ アプリケーションである場合のように、元のクエリに変更を加えることができない場合に便利です。プラン ガイドに指定されたクエリ ヒントは、コンパイルおよび最適化される前にクエリに追加されます。アドホック クエリの場合は、プラン ガイド ステートメントをテストするときだけ TABLE HINT 句を使用します。その他のアドホック クエリに対しては、テーブル ヒント内でのみこれらのヒントを指定することをお勧めします。

クエリ ヒントとして指定した場合、INDEX および FORCESEEK テーブル ヒントは次のオブジェクトに対して有効です。

  • テーブル

  • ビュー

  • インデックス付きビュー

  • 共通テーブル式 (ヒントは、結果セットが共通テーブル式に入力される SELECT ステートメントに指定する必要があります)

  • 動的管理ビュー

  • 名前付きサブクエリ

INDEX および FORCESEEK テーブル ヒントは、既存のテーブル ヒントを持たないクエリのクエリ ヒントとして指定できます。また、それぞれ、クエリ内の既存の INDEX または FORCESEEK ヒントの代わりに使用することもできます。INDEX および FORCESEEK 以外のテーブル ヒントは、クエリで既に WITH 句を使用してテーブル ヒントが指定されていない限り、クエリ ヒントとして使用できません。この場合に、そのクエリのセマンティックを維持するには、OPTION 句で TABLE HINT を使用して、対応するヒントもクエリ ヒントとして指定する必要があります。たとえば、クエリにテーブル ヒント NOLOCK が含まれている場合、プラン ガイドの @hints パラメーターの OPTION 句にも NOLOCK ヒントが含まれている必要があります。例 K を参照してください。INDEX または FORCESEEK 以外のテーブル ヒントが OPTION 句で TABLE HINT を使用して指定されている一方で対応するクエリ ヒントがない場合 (またはその逆の場合)、OPTION 句によりクエリのセマンティックが変更されることを示すエラー 8702 が発生し、クエリが失敗します。詳細については、「プラン ガイドでの INDEX および FORCESEEK のクエリ ヒントの使用」を参照してください。

A. MERGE JOIN を使用する

次の例では、クエリの JOIN 操作を MERGE JOIN によって実行することを指定します。

USE AdventureWorks;
GO
SELECT * 
FROM Sales.Customer AS c
INNER JOIN Sales.CustomerAddress AS ca ON c.CustomerID = ca.CustomerID
WHERE TerritoryID = 5
OPTION (MERGE JOIN);
GO

B. OPTIMIZE FOR を使用する

次の例では、クエリ オプティマイザーでのクエリの最適化時に、ローカル変数 @city\_name に値 'Seattle' を使用し、統計データを使用してローカル変数 @postal\_code の値を決定するように指定しています。

USE AdventureWorks;
GO
DECLARE @city_name nvarchar(30);
DECLARE @postal_code nvarchar(15);
SET @city_name = 'Ascheim';
SET @postal_code = 86171;
SELECT * FROM Person.Address
WHERE City = @city_name AND PostalCode = @postal_code
OPTION ( OPTIMIZE FOR (@city_name = 'Seattle', @postal_code UNKNOWN) );
GO

C. MAXRECURSION を使用する

MAXRECURSION を使用すると、不適切に作成された再帰共通テーブル式による無限ループの発生を防ぐことができます。次の例では、無限ループを意図的に作成し、MAXRECURSION ヒントを使用して再帰レベルの数を 2 に制限しています。

USE AdventureWorks;
GO
--Creates an infinite loop
WITH cte (EmployeeID, ManagerID, Title) AS
(
    SELECT EmployeeID, ManagerID, Title
    FROM HumanResources.Employee
    WHERE ManagerID IS NOT NULL
  UNION ALL
    SELECT cte.EmployeeID, cte.ManagerID, cte.Title
    FROM cte 
    JOIN  HumanResources.Employee AS e 
        ON cte.ManagerID = e.EmployeeID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT EmployeeID, ManagerID, Title
FROM cte
OPTION (MAXRECURSION 2);
GO

コードのエラーが訂正されると、MAXRECURSION は不要になります。

D. MERGE UNION を使用する

次の例では、MERGE UNION クエリ ヒントを使用します。

USE AdventureWorks;
GO
SELECT *
FROM HumanResources.Employee AS e1
UNION
SELECT *
FROM HumanResources.Employee AS e2
OPTION (MERGE UNION);
GO

E. HASH GROUP および FAST を使用する

次の例では、HASH GROUP および FAST クエリ ヒントを使用します。

USE AdventureWorks;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (HASH GROUP, FAST 10);
GO

F. MAXDOP を使用する

次の例では、MAXDOP クエリ ヒントを使用します。

USE AdventureWorks ;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (MAXDOP 2);
GO

G. INDEX を使用する

次の例では、INDEX ヒントを使用します。最初の例では、単独のインデックスを指定します。2 番目の例では、1 つのテーブル参照に対して複数のインデックスを指定します。INDEX ヒントはどちらの例においても別名が使用されているテーブルに適用されるので、公開されたオブジェクト名と同じ別名を TABLE HINT 句でも指定する必要があります。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide1', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX (IX_Employee_ManagerID)))';
GO
EXEC sp_create_plan_guide 
    @name = N'Guide2', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX(PK_Employee_EmployeeID, IX_Employee_ManagerID)))';
GO

H. FORCESEEK を使用する

次の例では、FORCESEEK テーブル ヒントを使用します。INDEX ヒントは 2 つの部分で構成される名前が使用されているテーブルに適用されるので、公開されたオブジェクト名と同じ 2 つの部分で構成される名前を TABLE HINT 句でも指定する必要があります。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide3', 
    @stmt = N'SELECT c.LastName, c.FirstName, HumanResources.Employee.Title
              FROM HumanResources.Employee
              JOIN Person.Contact AS c ON HumanResources.Employee.ContactID = c.ContactID
              WHERE HumanResources.Employee.ManagerID = 3
              ORDER BY c.LastName, c.FirstName;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT( HumanResources.Employee, FORCESEEK))';
GO

I. 複数のテーブル ヒントを使用する

次の例では、INDEX ヒントと FORCESEEK ヒントをそれぞれ別のテーブルに適用します。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide4', 
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_ManagerID ) ) 
                       , TABLE HINT ( c, FORCESEEK) )';
GO

J. TABLE HINT を使用して既存のテーブル ヒントをオーバーライドする

次の例では、ヒントを指定しないで TABLE HINT を使用し、クエリの FROM 句に指定されている INDEX テーブル ヒントの動作をオーバーライドする方法を示します。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide5', 
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e WITH (INDEX (IX_Employee_ManagerID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e))';
GO

K. セマンティックに作用するテーブル ヒントを指定する

次の例では、クエリに 2 つのテーブル ヒントが含まれています。1 つは、セマンティックに作用する NOLOCK で、もう 1 つはセマンティックに作用しない INDEX です。クエリのセマンティックを保持するために、プラン ガイドの OPTIONS 句に NOLOCK ヒントが指定されています。NOLOCK ヒントに加えて、INDEX および FORCESEEK ヒントが指定されているので、ステートメントをコンパイルおよび最適化するときにクエリのセマンティックに作用しない INDEX ヒントが置き換えられます。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide6', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_ManagerID) , NOLOCK, FORCESEEK ))';
GO

次の例では、クエリのセマンティックを保持し、テーブル ヒントに指定されている以外のインデックスをオプティマイザーが選択できるようにする別の方法を示します。これを実現するには、OPTIONS 句に (セマンティックに作用する) NOLOCK ヒントを指定する一方で、INDEX ヒントを持たないテーブル参照だけの TABLE HINT キーワードを指定します。

USE AdventureWorks;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide7', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e 
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, NOLOCK))';
GO