テーブル ヒント (Transact-SQL)
テーブル ヒントでは、ロック手法、1 つ以上のインデックス、クエリ処理操作 (テーブル スキャンやインデックスのシークなど)、またはその他のオプションを指定することによって、データ操作言語 (DML) ステートメントが存続する間だけ、クエリ オプティマイザーの既定の動作を無効にします。 テーブル ヒントは、DML ステートメントの FROM 句で指定され、その句で参照されるテーブルまたはビューのみに影響します。
注意 |
---|
通常、SQL Server クエリ オプティマイザーでは、クエリにとって最適な実行プランが選択されるため、ヒントは、経験を積んだ開発者やデータベース管理者が最後の手段としてのみ使用することをお勧めします。 |
適用対象
構文
WITH ( <table_hint> [ [, ]...n ] )
<table_hint> ::=
[ NOEXPAND ] {
INDEX ( index_value [ ,...n ] ) | INDEX = ( index_value ) | FORCESEEK [( index_value ( index_column_name [ ,... ] ) ) ]
| FORCESCAN
| FORCESEEK
| HOLDLOCK
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SPATIAL_WINDOW_MAX_CELLS = integer
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
<table_hint_limited> ::=
{
KEEPIDENTITY
| KEEPDEFAULTS
| HOLDLOCK
| IGNORE_CONSTRAINTS
| IGNORE_TRIGGERS
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
引数
WITH ( <table_hint> ) [ [, ]...n ]
いくつかの例外を除き、テーブル ヒントは、FROM 句で WITH キーワードを使用して指定した場合にのみサポートされます。 また、テーブル ヒントはかっこを使用して指定する必要があります。重要 WITH キーワードを省略することは推奨されていません。この機能は、将来のバージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、この機能の使用を避け、現在この機能を使用しているアプリケーションは修正するようにしてください。
WITH キーワードの有無にかかわらず使用できるテーブル ヒントは、NOLOCK、READUNCOMMITTED、UPDLOCK、REPEATABLEREAD、SERIALIZABLE、READCOMMITTED、TABLOCK、TABLOCKX、PAGLOCK、ROWLOCK、NOWAIT、READPAST、XLOCK、および NOEXPAND です。 これらのテーブル ヒントを WITH キーワードを使用せずに指定するときは、単独で指定してください。 次にその例を示します。
FROM t (TABLOCK)
ヒントを他のオプションと一緒に指定する場合は、次のように WITH キーワードを使用して指定する必要があります。
FROM t WITH (TABLOCK, INDEX(myindex))
複数のテーブル ヒント間にはコンマを使用することをお勧めします。
重要 ヒントの分割にコンマの代わりにスペースを用いる方法は推奨されていません。この機能は、Microsoft SQL Server の将来のバージョンで削除されます。新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションはできるだけ早く修正してください。
この制限は、互換性レベル 90 以上のデータベースに対するクエリでヒントを使用する場合に適用されます。
NOEXPAND
クエリ オプティマイザーがクエリを処理する場合に、インデックス付きビューが展開されず、基になるテーブルがアクセスされないことを指定します。 クエリ オプティマイザーは、ビューをクラスター化インデックスを持つテーブルのように取り扱います。 NOEXPAND はインデックス付きビューにのみ適用できます。 詳細については、「説明」を参照してください。INDEX (index_value [,... n] ) | INDEX = ( index_value**)**
INDEX() 構文では、ステートメントを処理するときにクエリ オプティマイザーが使用する 1 つ以上のインデックスの名前または ID を指定します。 一方、INDEX = 構文では、単一のインデックス値を指定します。 各テーブルに対して指定できるのは 1 つのインデックス ヒントだけです。クラスター化インデックスがある場合、INDEX(0) はクラスター化インデックスのスキャンを実行し、INDEX(1) はクラスター化インデックスのスキャンまたはシークを実行します。 クラスター化インデックスがない場合、INDEX(0) はテーブル スキャンを実行し、INDEX(1) はエラーと見なされます。
1 つのヒント リストの中で複数のインデックスが使用されている場合、重複するものは無視され、リスト内の残りのインデックスを使用してテーブルの行が取得されます。 インデックス ヒント内のインデックスの順番は重要です。 複数のインデックス ヒントはインデックスの AND 処理も設定し、クエリ オプティマイザーはアクセスされる各インデックスに可能な限り多くの条件を適用します。 ヒント インデックスの集合に、クエリで参照される列のすべてが含まれているわけではない場合、SQL Server データベース エンジンがすべてのインデックス列を取得した後で、残りの列を取得するフェッチが実行されます。
注 複数のインデックスを参照するインデックス ヒントが、スター結合のファクト テーブルで使用されている場合、オプティマイザーはそのインデックス ヒントを無視し、警告メッセージを返します。 また、インデックス論理和は、インデックス ヒントが指定されたテーブルでは許可されません。
テーブル ヒント内のインデックスの最大個数は、非クラスター化インデックスが 250 個です。
KEEPIDENTITY
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。インポートしたデータ ファイルの ID 値 (複数可) を ID 列に使用することを指定します。 KEEPIDENTITY を指定しない場合、この列の ID 値は確認されるのみでインポートされません。クエリ オプティマイザーは、テーブルの作成時に指定された seed および increment の値を基に一意な値を自動的に割り当てます。
重要 テーブルやビューの ID 列の値がデータ ファイルに含まれておらず、ID 列がテーブルの最終列でもない場合は、その ID 列をスキップする必要があります。 詳細については、「フォーマット ファイルを使用したデータ フィールドのスキップ (SQL Server)」を参照してください。 ID 列のスキップに成功すると、クエリ オプティマイザーは、その ID 列の一意な値を、インポートされたテーブル行に自動的に割り当てます。
このヒントを INSERT ... SELECT * FROM OPENROWSET(BULK...) ステートメントで使用する例については、「データの一括インポート時の ID 値の保持 (SQL Server)」を参照してください。
テーブルの ID 値の確認については、「DBCC CHECKIDENT (Transact-SQL)」を参照してください。
KEEPDEFAULTS
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。データ レコードにテーブルの列値が含まれていない場合に、NULL の代わりにテーブル列の既定値を挿入することを指定します。
このヒントを INSERT ... SELECT * FROM OPENROWSET(BULK...) ステートメントで使用する例については、「一括インポート中の NULL の保持または既定値の使用 (SQL Server)」を参照してください。
FORCESEEK [ **(index_value(**index_column_name [ ,... n ] )) ]
クエリ オプティマイザーに対し、テーブルやビューのデータへのアクセス パスとしてインデックスのシーク操作のみを使用することを指定します。 SQL Server 2008 R2 SP1 以降では、インデックス パラメーターも指定できます。 その場合、一度でも指定されたインデックス列が使用されると、クエリ オプティマイザーでは指定されたインデックスを介したインデックスのシーク操作のみが検討されます。index_value
インデックスの名前またはインデックスの ID 値です。 インデックス ID 0 (ヒープ) は指定できません。 インデックスの名前または ID を返すには、sys.indexes カタログ ビューにクエリを実行します。index_column_name
シーク操作に含めるインデックス列の名前です。 インデックス パラメーターを使用して FORCESEEK を指定することは、INDEX ヒントを使用して FORCESEEK を使用することと同じです。 ただし、シーク対象のインデックスとシーク操作で考慮するインデックス列の両方を指定することで、クエリ オプティマイザーで使用されるアクセス パスをより詳細に制御できるようになります。 オプティマイザーでは、必要に応じて、追加の列が検討される場合もあります。 たとえば、非クラスター化インデックスが指定されている場合、オプティマイザーでは、指定された列に加え、クラスター化インデックスのキー列を使用することもできます。
FORCESEEK ヒントは以下の方法で指定できます。
構文
例
説明
インデックスまたは INDEX ヒントを使用しない場合
FROM dbo.MyTable WITH (FORCESEEK)
クエリ オプティマイザーでは、関連するインデックスを介してテーブルやビューにアクセスするためのインデックスのシーク操作のみが検討されます。
INDEX ヒントと組み合わせた場合
FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex))
クエリ オプティマイザーでは、指定されたインデックスを介してテーブルやビューにアクセスするためのインデックスのシーク操作のみが検討されます。
インデックスとインデックス列を指定してパラメーター化する場合
FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3)))
少なくとも指定されたインデックス列を使用した場合、クエリ オプティマイザーでは、指定されたインデックスを介してテーブルやビューにアクセスするためのインデックスのシーク操作のみが検討されます。
(インデックス パラメーターを使用するかどうかにかかわらず) FORCESEEK ヒントを使用する際は、次のガイドラインを考慮してください。
ヒントは、テーブル ヒントまたはクエリ ヒントとして指定できます。 クエリ ヒントの詳細については、「クエリ ヒント (Transact-SQL)」を参照してください。
インデックス付きビューに FORCESEEK を適用するには、NOEXPAND ヒントも指定する必要があります。
ヒントは、テーブルまたはビューごとに 1 回だけ適用できます。
ヒントは、リモート データ ソースに指定できません。 インデックス ヒントを使用して FORCESEEK を指定すると、エラー 7377 が返されます。また、インデックス ヒントなしで FORCESEEK を使用すると、エラー 8180 が返されます。
FORCESEEK が原因でプランが見つからない場合、エラー 8622 が返されます。
インデックス パラメーターを使用して FORCESEEK を指定する際は、次のガイドラインと制限が適用されます。
ヒントは、INSERT、UPDATE、または DELETE ステートメントの対象であるテーブルには指定できません。
ヒントは、INDEX ヒントまたは別の FORCESEEK ヒントと組み合わせて指定することができません。
少なくとも 1 列を指定する必要があり、先頭のキー列にする必要があります。
追加のインデックス列を指定できますが、キー列は省略できません。 たとえば、指定されたインデックスに a、b、および c というキー列が含まれている場合、有効な構文には FORCESEEK (MyIndex (a)) および FORCESEEK (MyIndex (a, b) が含まれます。 無効な構文には、FORCESEEK (MyIndex (c)) と FORCESEEK (MyIndex (a, c) が含まれます。
ヒントで指定された列名の順序は、参照先のインデックスでの列の順序と一致させる必要があります。
インデックス キーの定義にない列は、指定できません。 たとえば、非クラスター化インデックスでは、定義されたインデックス キー列のみを指定できます。 自動的にインデックスに含まれるクラスター化キー列は指定できませんが、オプティマイザーでは使用できます。
xVelocity メモリ最適化列ストア インデックスは、インデックス パラメーターとして指定できません。 エラー 366 が返されます。
インデックス定義を変更すると (列の追加や削除など)、そのインデックスを参照するクエリに対する変更も必要になる場合があります。
ヒントを使用すると、オプティマイザーでは、テーブル上の空間インデックスまたは XML インデックスが検討されなくなります。
ヒントは、FORCESCAN ヒントと組み合わせて指定することはできません。
パーティション インデックスでは、SQL Server によって暗黙的に追加されたパーティション分割列を FORCESEEK ヒントで指定できません。
注意 パラメーターを使用して FORCESEEK を指定すると、オプティマイザーで考慮できるプラン数の制限は、パラメーターなしで FORCESEEK を指定した場合よりも多くなります。 これにより、"プランを生成できない" というエラーが生じる回数が増加する可能性があります。 将来のリリースでは、オプティマイザーに対して内部変更を行うため、より多くのプランを考慮できるようになります。
FORCESCAN
SQL Server 2008 R2 SP1 で導入されたこのヒントは、参照されているテーブルやビューへのアクセス パスとしてクエリ オプティマイザーでインデックス スキャン操作のみを使用するように指定します。 FORCESCAN ヒントは、オプティマイザーが影響を受ける行数を過小評価し、スキャン操作ではなくシーク操作を選択するクエリに役立つ場合があります。 この場合、操作に許可されるメモリの量は少なすぎて、クエリのパフォーマンスに影響します。FORCESCAN を指定する際には、INDEX ヒントを使用してもしなくてもかまいません。 インデックス ヒントと組み合わせると (INDEX = index_name, FORCESCAN)、クエリ オプティマイザーでは、参照されるテーブルにアクセスする際に、指定されたインデックスを介したアクセス パスのみが検討されます。 FORCESCAN を指定する際に、インデックス ヒント INDEX(0) を使用すると、ベース テーブルにテーブル スキャン操作を実行できます。
パーティション テーブルやパーティション インデックスの場合、FORCESCAN が適用されるのは、クエリの述語評価によってパーティションが削除された後です。 つまり、スキャンは、テーブル全体ではなく、残りのパーティションのみに適用されます。
FORCESCAN ヒントには次の制限があります。
ヒントは、INSERT、UPDATE、または DELETE ステートメントの対象であるテーブルには指定できません。
ヒントは、複数のインデックス ヒントと併用できません。
ヒントを使用すると、オプティマイザーでは、テーブル上の空間インデックスまたは XML インデックスが検討されなくなります。
ヒントは、リモート データ ソースに指定できません。
ヒントは、FORCESEEK ヒントと組み合わせて指定することはできません。
HOLDLOCK
SERIALIZABLE に相当します。 詳細については、後の「SERIALIZABLE」を参照してください。 HOLDLOCK は、指定されたテーブルやビューに対してのみ、また、使用されているステートメントによって定義されたトランザクションの間のみ適用されます。 HOLDLOCK は、FOR BROWSE オプションを含む SELECT ステートメントでは使用できません。IGNORE_CONSTRAINTS
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。テーブルに対する制約を一括インポート操作時に無視することを指定します。 既定では、UNIQUE 制約と CHECK 制約および主キー制約と外部キー制約が INSERT によってチェックされます。 一括インポート操作の際に IGNORE_CONSTRAINTS を指定している場合、インポート対象のテーブルに対する制約が無視されます。 UNIQUE、PRIMARY KEY、または NOT NULL の各制約を無効にすることはできません。
制約に違反する行が入力データに含まれている場合に、CHECK 制約および FOREIGN KEY 制約を無効化することができます。 CHECK 制約および FOREIGN KEY 制約を無効化することによって、データをインポートしてから、Transact-SQL ステートメントを使用してデータをクリーンアップできます。
CHECK 制約および FOREIGN KEY 制約を無視すると、操作の後、テーブルに設定されている制約のうち、無視された制約は sys.check_constraints カタログ ビューまたは sys.foreign_keys カタログ ビューで is_not_trusted とマークされます。 テーブル全体の制約は、任意の時点で必ず検証してください。 一括インポート操作の前にテーブルが空白になっていない場合、制約の再検証にかかるコストは、CHECK 制約および FOREIGN KEY 制約を増分データに適用することによるコストを上回る可能性があります。
IGNORE_TRIGGERS
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。テーブルに対して定義されたトリガーを、一括インポート操作時に無視することを指定します。 既定では、INSERT はトリガーを適用します。
アプリケーションがいずれのトリガーにも依存しておらず、パフォーマンスの最大化が重要な場合にのみ、IGNORE_TRIGGERS を使用してください。
NOLOCK
READUNCOMMITTED に相当します。 詳細については、後の「READUNCOMMITTED」を参照してください。注 UPDATE ステートメントまたは DELETE ステートメントの場合 : この機能は、将来のバージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、この機能の使用を避け、現在この機能を使用しているアプリケーションは修正するようにしてください。
NOWAIT
テーブルでロックがかかったらすぐにメッセージを返すようにデータベース エンジンを設定します。 NOWAIT は、特定のテーブルに SET LOCK_TIMEOUT 0 を指定することに相当します。 NOWAIT ヒントは、TABLOCK ヒントも指定されている場合は機能しません。 TABLOCK ヒントを使用している場合に待機しないでクエリを終了するには、代わりにクエリの前に SETLOCK_TIMEOUT 0; を指定します。PAGLOCK
通常使用される行やキーに対する個々のロックまたは単一のテーブル ロックの代わりに、ページ ロックを使用します。 既定では、操作に適したロック モードを使用します。 SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定しても、UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定しない限り、ページ ロックは取得されません。READCOMMITTED
読み取り操作が、ロックまたは行のバージョン管理を使用して、READ COMMITTED 分離レベルのルールに従うことを指定します。 データベース オプション READ_COMMITTED_SNAPSHOT が OFF の場合、データベース エンジンはデータの読み取り時に共有ロックを取得し、読み取り操作が完了するとロックを解除します。 データベース オプション READ_COMMITTED_SNAPSHOT が ON の場合、データベース エンジンはロックを取得せずに行のバージョン管理を使用します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。注 UPDATE ステートメントまたは DELETE ステートメントの場合 : この機能は、将来のバージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、この機能の使用を避け、現在この機能を使用しているアプリケーションは修正するようにしてください。
READCOMMITTEDLOCK
読み取り操作が、ロックを使用して、READ COMMITTED 分離レベルのルールに従うことを指定します。 READ_COMMITTED_SNAPSHOT データベース オプションの設定にかかわらず、データベース エンジン はデータの読み取り時に共有ロックを取得し、読み取り操作が完了するとロックを解除します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。 このヒントは、INSERT ステートメントの対象のテーブルには指定できません。指定すると、エラー 4140 が返されます。READPAST
他のトランザクションによってロックされている行を、データベース エンジン が読み取らないことを指定します。 READPAST を指定すると、行レベルのロックがスキップされます。 つまり、データベース エンジンは、ロックが解除されるまで現在のトランザクションをブロックする代わりに、行をスキップします。 たとえば、テーブル T1 に整数型の列が 1 つあり、値 1、2、3、4、5 が格納されているとします。 このテーブルに対してトランザクション A で値 3 を 8 に変更し、この変更をまだコミットしていない間に SELECT * FROM T1 (READPAST) を実行すると、取得される値は 1、2、4、5 となります。 READPAST は主に、SQL Server テーブルを使用する作業キューの実装時に、ロックの競合を減らすために使用します。 READPAST を使用するキュー リーダーは、他のトランザクションによってロックされたキュー エントリを、ロックが解除されるまで待たずにスキップして、次に使用可能なキュー エントリへ進みます。READPAST は、UPDATE ステートメントまたは DELETE ステートメントで参照されるテーブル、および FROM 句で参照されるテーブルで指定できます。 UPDATE ステートメントで READPAST を指定した場合、ステートメント内での指定場所にかかわらず、更新対象レコード特定のためのデータ読み取り時にだけ適用されます。 INSERT ステートメントの INTO 句では、テーブルに READPAST を指定することができません。 READPAST を使用する読み取り操作はブロックを行いません。 READPAST を使用する更新操作や削除操作は、外部キーやインデックス付きビューの読み取り時、またはセカンダリ インデックスの変更時にブロックを行う場合があります。
READPAST は、READ COMMITTED 分離レベルまたは REPEATABLE READ 分離レベルで実行中のトランザクションでのみ指定できます。 SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定する場合、UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定する必要があります。
READ_COMMITTED_SNAPSHOT データベース オプションが ON に設定され、次のいずれかの条件に該当する場合、READPAST テーブル ヒントは指定できません。
セッションのトランザクション分離レベルが READ COMMITTED の場合
READCOMMITTED テーブル ヒントもクエリで指定されている場合
このような場合に READPAST ヒントを指定するには、READCOMMITTED テーブル ヒントがある場合は削除し、クエリに READCOMMITTEDLOCK テーブル ヒントを含めます。
READUNCOMMITTED
ダーティ リードを許可することを指定します。 現在のトランザクションによるデータ読み取りが他のトランザクションによって変更されないようにするため共有ロックを実行しません。また、他のトランザクションによって排他ロックが設定されていても、ロックされたデータの現在のトランザクションによる読み取りはブロックされません。 ダーティ リードを許可すると同時実行性が高まりますが、他のトランザクションによってロールバックされているデータ変更を読み取る可能性があります。 この結果、トランザクションでエラーが発生したり、コミットされていないデータがユーザーに提示されたり、レコードが重複表示されたりまったく表示されなかったりする場合があります。READUNCOMMITTED ヒントと NOLOCK ヒントはデータのロックにのみ適用されます。 READUNCOMMITTED ヒントおよび NOLOCK ヒントを含むクエリを含め、すべてのクエリは、コンパイル中と実行中にスキーマ安定度 (Sch-S) ロックを取得します。 このため、同時実行トランザクションがテーブルの Sch-M (スキーマ修正) ロックを保持している場合、クエリはブロックされます。 たとえば、データ定義言語 (DDL) 操作では、テーブルのスキーマ情報を変更する前に Sch-M ロックを獲得します。 READUNCOMMITTED ヒントまたは NOLOCK ヒントを指定して実行しているクエリを含め、すべての同時実行クエリは、スキーマ安定度 (Sch-S) ロックを取得しようとするとブロックされます。 一方、Sch-S ロックを保持するクエリによって、Sch-M ロックを取得しようとする同時実行トランザクションはブロックされます。
READUNCOMMITTED および NOLOCK は、挿入、更新、削除の各操作によって変更されるテーブルに対しては指定できません。 SQL Server クエリ オプティマイザーは、UPDATE ステートメントまたは DELETE ステートメントの対象テーブルに適用する FROM 句内の READUNCOMMITTED ヒントおよび NOLOCK ヒントを無視します。
注 FROM 句を UPDATE または DELETE ステートメントの対象テーブルに適用する場合、この句での READUNCOMMITTED ヒントおよび NOLOCK ヒントの使用は、将来のバージョンの SQL Server でサポートされなくなる予定です。 新しい開発作業ではこのコンテキストでのヒントの使用を避け、現在このヒントを使用しているアプリケーションは変更を検討してください。
次のいずれかを使用することによって、ロックの競合を最小限に抑えながら、コミットされていないデータ変更のダーティ リードからトランザクションを保護することができます。
READ COMMITTED 分離レベル。READ_COMMITTED_SNAPSHOT データベース オプションを ON に設定します。
SNAPSHOT 分離レベル。
分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。
注 READUNCOMMITTED が指定されているときにエラー メッセージ 601 が表示された場合は、デッドロック エラー (1205) を解決するときと同じように解決し、ステートメントを再実行してください。
REPEATABLEREAD
REPEATABLE READ 分離レベルで実行しているトランザクションと同じロック セマンティクスでスキャンを実行することを指定します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。ROWLOCK
通常取得されるページ ロックまたはテーブル ロックの代わりに、行ロックを取得することを指定します。 SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定しても、UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定しない限り、行ロックは取得されません。SPATIAL_WINDOW_MAX_CELLS = integer
geometry オブジェクトや geography オブジェクトのテセレーションに使用するセルの最大数を指定します。 number は、1 ~ 8192 の範囲の値です。このオプションを使用すると、プライマリとセカンダリのフィルターの実行時間の間のトレードオフを調整することによって、クエリの実行時間を微調整できます。 値を大きくすると、セカンダリ フィルターの実行時間が短縮されますが、プライマリ フィルターの実行時間が増加します。値を小さくすると、プライマリ フィルターの実行時間が短縮されますが、セカンダリ フィルターの実行時間が増加します。 密度の高い空間データの場合は、大きい値を指定して、プライマリ フィルターでより適切な近似値を提供し、セカンダリ フィルターの実行時間を減少させることで、実行時間を短縮させます。 密度の低いデータでは、小さい値を指定して、プライマリ フィルターの実行時間を短縮させます。
このオプションは、手動と自動の両方のグリッド テセレーションに使用できます。
SERIALIZABLE
HOLDLOCK に相当します。 共有ロックがより制限的になります。テーブルまたはデータ ページが不要になったときに、トランザクションが完了しているかどうかにかかわらず共有ロックが解除されるのではなく、共有ロックはトランザクションが完了するまで保持されます。 SERIALIZABLE 分離レベルで実行しているトランザクションと同じセマンティクスで、スキャンが実行されます。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。TABLOCK
取得したロックがテーブル レベルで適用されることを指定します。 取得されるロックの種類は、実行されるステートメントによって異なります。 たとえば、SELECT ステートメントを実行すると、共有ロックが取得されます。 TABLOCK を指定することで、行レベルまたはページ レベルではなくテーブル全体に共有ロックが適用されます。 HOLDLOCK も指定してある場合は、テーブル ロックがトランザクション終了まで保持されます。INSERT INTO <対象テーブル> SELECT <列> FROM <ソース テーブル> ステートメントを使用してデータをヒープにインポートするときに、対象テーブルに対して TABLOCK ヒントを指定すると、そのステートメントに対してログ記録とロックの最適化を有効にすることができます。 データベース復旧モデルが単純復旧モデルまたは一括ログ復旧モデルに設定されている必要もあります。 詳細については、「INSERT (Transact-SQL)」を参照してください。
テーブルにデータをインポートするため、OPENROWSET 一括行セット プロバイダーで TABLOCK を使用すると、対象テーブルへのデータ読み込みを、ログ記録とロックを最適化して、複数のクライアントで同時に行うことができます。 詳細については、「一括インポートで最小ログ記録を行うための前提条件」を参照してください。
TABLOCKX
テーブルに排他ロックを使用することを指定します。UPDLOCK
更新ロックを使用することと、これをトランザクション終了まで保持することを指定します。 UPDLOCK を使用すると、行レベルまたはページ レベルの読み取り操作のみに更新ロックが適用されます。 UPDLOCK を TABLOCK と組み合わせたり、なんらかの理由でテーブル レベルのロックが使用されたりすると、代わりに排他 (X) ロックが取得されます。UPDLOCK を指定すると、READCOMMITTED および READCOMMITTEDLOCK 分離レベル ヒントが無視されます。 たとえば、セッションの分離レベルを SERIALIZABLE に設定し、クエリで (UPDLOCK, READCOMMITTED) を指定すると、READCOMMITTED ヒントは無視され、トランザクションは SERIALIZABLE 分離レベルを使用して実行されます。
XLOCK
排他ロックを使用することと、これをトランザクション終了まで保持することを指定します。 ROWLOCK、PAGLOCK、または TABLOCK と組み合わせて指定すると、排他ロックは適切な粒度レベルに適用されます。
説明
テーブルがクエリ プランによってアクセスされているのではない場合、テーブル ヒントは無視されます。 これは、オプティマイザーがテーブルにまったくアクセスしないことを選択した結果であるか、またはインデックス付きビューが代わりにアクセスされるためである可能性があります。 後者の場合、OPTION (EXPAND VIEWS) クエリ ヒントを使用することで、インデックス付きビューへのアクセスを防ぐことができます。
すべてのロック ヒントが、クエリ プランによってアクセスされているすべてのテーブルおよびビュー (ビューで参照されているテーブルおよびビューを含む) に反映されます。 また、SQL Server は、対応するロックの一貫性チェックを実行します。
行レベルのロックを取得するロック ヒント ROWLOCK、UPDLOCK、および XLOCK では、実際のデータ行ではなくインデックス キーに対してロックが実行される場合があります。 たとえば、テーブルに非クラスター化インデックスがあり、ロック ヒントを使用する SELECT ステートメントがカバーするインデックスによって処理される場合、ベース テーブルのデータ行ではなく、カバーするインデックスのインデックス キーに対してロックが取得されます。
テーブルに計算列があり、その計算列が、別のテーブル内の列にアクセスする式や関数によって計算される場合、テーブル ヒントがそのテーブル上で使用されることや、反映されることはありません。 たとえば、クエリ内のテーブルに NOLOCK テーブル ヒントが指定されているものとします。 このテーブルには、別のテーブル内の列にアクセスする式と関数の組み合わせで計算される、計算列があります。 式と関数で参照されるテーブルが、アクセスされるときに NOLOCK テーブル ヒントを使用することはありません。
SQL Server では、FROM 句内の各テーブルに対して、次の各グループの複数のテーブル ヒントが許可されません。
粒度ヒント: PAGLOCK、NOLOCK、READCOMMITTEDLOCK、ROWLOCK、TABLOCK、TABLOCKX
分離レベル ヒント: HOLDLOCK、NOLOCK、READCOMMITTED、REPEATABLEREAD、SERIALIZABLE
フィルター選択されたインデックス ヒント
フィルター選択されたインデックスをテーブル ヒントとして使用できますが、クエリで選択する行のすべてがカバーされているわけではない場合、クエリ オプティマイザーからエラー 8622 が返されます。 フィルター選択されたインデックス ヒントが無効になる例を次に示します。 この例では、フィルター選択されたインデックス FIBillOfMaterialsWithComponentID を作成し、SELECT ステートメントのインデックス ヒントとして使用します。 フィルター選択されたインデックスの述語には、ComponentID が 533、324、および 753 のデータ行が含まれています。 クエリ述語にも ComponentID が 533、324、および 753 のデータ行が含まれていますが、フィルター選択されたインデックスには存在しない ComponentID 855 および 924 も結果セットに含めるよう拡張されています。 したがって、クエリ オプティマイザーはフィルター選択されたインデックス ヒントを使用できず、エラー 8622 が生成されます。 詳細については、「フィルター選択されたインデックスの作成」を参照してください。
USE AdventureWorks2012;
GO
IF EXISTS (SELECT name FROM sys.indexes
WHERE name = N'FIBillOfMaterialsWithComponentID'
AND object_id = OBJECT_ID(N'Production.BillOfMaterials'))
DROP INDEX FIBillOfMaterialsWithComponentID
ON Production.BillOfMaterials;
GO
CREATE NONCLUSTERED INDEX "FIBillOfMaterialsWithComponentID"
ON Production.BillOfMaterials (ComponentID, StartDate, EndDate)
WHERE ComponentID IN (533, 324, 753);
GO
SELECT StartDate, ComponentID FROM Production.BillOfMaterials
WITH( INDEX (FIBillOfMaterialsWithComponentID) )
WHERE ComponentID in (533, 324, 753, 855, 924);
GO
フィルター選択されたインデックスに必要な値が SET オプションにない場合、クエリ オプティマイザーはインデックス ヒントを無視します。 詳細については、「CREATE INDEX (Transact-SQL)」を参照してください。
NOEXPAND の使用
NOEXPAND はインデックス付きビューにのみ適用できます。 インデックス付きビューとは、一意なクラスター化インデックスが作成されているビューを示します。 インデックス付きビューおよびベース テーブルの両方に存在する列への参照がクエリに含まれていて、クエリ オプティマイザーがクエリの実行にインデックス付きビューを使用する方が最適であると判断した場合、クエリ オプティマイザーはビューのインデックスを利用します。 この機能は、インデックス付きビューのマッチングと呼ばれます。 SQL Server の特定のエディションでのみ、クエリ オプティマイザーではインデックス付きビューが自動的に使用されます。 SQL Server の各エディションでサポートされる機能の一覧については、「SQL Server 2012 の各エディションがサポートする機能」を参照してください。
ただし、オプティマイザーで、インデックス付きビューのマッチングを検討したり、NOEXPAND ヒントで参照されるインデックス付きビューを使用したりするには、以下の SET オプションを ON に設定する必要があります。
ANSI_NULLS |
ANSI_WARNINGS |
CONCAT_NULL_YIELDS_NULL |
ANSI_PADDING |
ARITHABORT1 |
QUOTED_IDENTIFIERS |
1 ARITHABORT は、ANSI_WARNINGS が ON に設定されている場合は、暗黙的に ON に設定されます。 したがって、この設定を手動で調整する必要はありません。
また、NUMERIC_ROUNDABORT オプションは OFF に設定する必要があります。
オプティマイザーがインデックス付きビューのインデックスを使用するように強制するには、NOEXPAND オプションを指定します。 このヒントは、ビューがクエリ内でも指定されている場合にのみ使用できます。 SQL Server では、FROM 句で直接ビューを指定していないクエリで、特定のインデックス付きビューが使用されるようにするヒントは用意されていません。しかし、クエリ オプティマイザーでは、インデックス付きビューがクエリで直接参照されていなくても、その使用が検討されます。
クエリ ヒントとしてのテーブル ヒントの使用
OPTION (TABLE HINT) 句を使用すると、テーブル ヒントをクエリ ヒントとして指定することもできます。 プラン ガイドのコンテキスト内でのみ、テーブル ヒントをクエリ ヒントとして使用することをお勧めします。 アドホック クエリに対しては、これらのヒントをテーブル ヒントとしてのみ指定します。 詳細については、「クエリ ヒント (Transact-SQL)」を参照してください。
権限
KEEPIDENTITY、IGNORE_CONSTRAINTS、IGNORE_TRIGGERS の各ヒントには、テーブルに対する ALTER 権限が必要です。
使用例
A. TABLOCK ヒントを使用してロック手法を指定する
次の例では、Production.Product テーブルに対して共有ロックを使用することと、このロックを UPDATE ステートメントの終了まで保持することを指定します。
USE AdventureWorks2012;
GO
UPDATE Production.Product
WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO
B. FORCESEEK ヒントを使用したインデックスのシーク操作の指定
次の例では、インデックスを指定せずに FORCESEEK ヒントを使用して、Sales.SalesOrderDetail テーブルに対するインデックスのシーク操作を実行するようにクエリ オプティマイザーを設定します。
USE AdventureWorks2012;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESEEK)
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO
次の例では、インデックスを指定して FORCESEEK ヒントを使用して、指定したインデックスおよびインデックス列に対してインデックスのシーク操作を実行するようにクエリ オプティマイザーを設定します。
USE AdventureWorks2012;
GO
SELECT h.SalesOrderID, h.TotalDue, d.OrderQty
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d
WITH (FORCESEEK (PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID (SalesOrderID)))
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO
C. FORCESCAN ヒントを使用してインデックスのスキャン操作を指定する
次の例では、FORCESCAN ヒントを使用して、Sales.SalesOrderDetail テーブルに対するスキャン操作を実行するようにクエリ オプティマイザーを設定します。
USE AdventureWorks2012;
GO
SELECT h.SalesOrderID, h.TotalDue, d.OrderQty
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d
WITH (FORCESCAN)
ON h.SalesOrderID = d.SalesOrderID
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);