テーブル ヒント (Transact-SQL)
更新 : 2006 年 12 月 12 日
クエリ オプティマイザが、テーブル スキャンや 1 つ以上のインデックスを使用することを指定します。また、このテーブルやビューとこの SELECT、INSERT、UPDATE、DELETE の各ステートメントに対するロック手法を使用することも指定します。この指定は省略可能です。ヒントが指定されない場合でも、通常、クエリ オプティマイザは最適な方法を選択します。
重要 : |
---|
通常、SQL Server 2005 クエリ オプティマイザでは、クエリにとって最適な実行プランが選択されるため、<table_hint> を含むヒントは、経験を積んだ開発者やデータベース管理者が最後の手段としてのみ使用することをお勧めします。 |
適用対象
構文
<table_hint> ::=
[ NOEXPAND ] {
INDEX ( index_val [ ,...n ] )
| FASTFIRSTROW
| HOLDLOCK
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
<table_hint_limited> ::=
{
KEEPIDENTITY
| KEEPDEFAULTS
| FASTFIRSTROW
| HOLDLOCK
| IGNORE_CONSTRAINTS
| IGNORE_TRIGGERS
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
引数
- NOEXPAND
クエリ オプティマイザがクエリを処理する場合に、インデックス付きビューが展開されず、基になるテーブルがアクセスされないことを指定します。クエリ オプティマイザは、ビューをクラスタ化インデックスを持つテーブルのように取り扱います。NOEXPAND はインデックス付きビューにのみ適用できます。詳細については、「解説」を参照してください。
INDEX ( index_val [ ,... n ] ) ] )
ステートメントを処理するときにクエリ オプティマイザが使用するインデックスの名前または ID を指定します。各テーブルに対して指定できるのは 1 つのインデックス ヒントだけです。クラスタ化インデックスがある場合、INDEX(0) はクラスタ化インデックスのスキャンを実行し、INDEX(1) はクラスタ化インデックスのスキャンまたはシークを実行します。クラスタ化インデックスがない場合、INDEX(0) はテーブル スキャンを実行し、INDEX(1) はエラーと見なされます。
代わりに、INDEX = 構文では、単一のインデックス ヒントを指定します。これは、旧バージョンとの互換性を保つ目的でのみサポートされています。
1 つのヒント リストの中で複数のインデックスが使用されている場合、重複するものは無視され、リスト内の残りのインデックスを使用してテーブルの行が取得されます。インデックス ヒント内のインデックスの順番は重要です。複数のインデックス ヒントはインデックスの AND 処理も設定し、クエリ オプティマイザはアクセスされる各インデックスに可能な限り多くの条件を適用します。ヒント インデックスの集合で対処できない場合は、SQL Server 2005 データベース エンジンがすべてのインデックス列を取得した後で、フェッチが実行されます。
メモ : 複数のインデックスを参照するインデックス ヒントが、スター型結合のファクト テーブルで使用されている場合、オプティマイザはそのインデックス ヒントを無視し、警告メッセージを返します。また、インデックス論理和は、インデックス ヒントが指定されたテーブルでは許可されません。 テーブル ヒント内のインデックスの最大個数は、非クラスタ化インデックスが 250 個です。
KEEPIDENTITY
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。インポートしたデータ ファイルの ID 値 (複数可) を ID 列に使用することを指定します。KEEPIDENTITY を指定しない場合、この列の ID 値は確認されるのみでインポートされません。クエリ オプティマイザは、テーブルの作成時に指定された seed および increment の値を基に一意な値を自動的に割り当てます。
重要 : テーブルやビューの ID 列の値がデータ ファイルに含まれていない場合には、ID 列がテーブルの最終列でない限り、その ID 列をスキップする必要があります。詳細については、「フォーマット ファイルを使用したデータ フィールドのスキップ」を参照してください。ID 列のスキップに成功すると、クエリ オプティマイザは、その ID 列の一意な値を、インポートされたテーブル行に自動的に割り当てます。 このヒントを INSERT ...SELECT * FROM OPENROWSET(BULK...) ステートメントで使用する例については、「データの一括インポート時の ID 値の保持」を参照してください。
テーブルの ID 値の確認については、「DBCC CHECKIDENT (Transact-SQL)」を参照してください。
KEEPDEFAULTS
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。データ レコードにテーブルの列値が含まれていない場合に、NULL の代わりに列の既定値を挿入することを指定します。
このヒントを INSERT ...SELECT * FROM OPENROWSET(BULK...) ステートメントで使用する例については、「一括インポート中の NULL の保持または既定値の使用」を参照してください。
- FASTFIRSTROW
OPTION (FAST 1) に相当します。詳細については、SELECT の OPTION 句の FAST を参照してください。
- HOLDLOCK
SERIALIZABLE に相当します。詳細については、後の「SERIALIZABLE」を参照してください。HOLDLOCK は、指定されたテーブルやビューに対してのみ、また、使用されているステートメントによって定義されたトランザクションの間のみ適用されます。HOLDLOCK は、FOR BROWSE オプションを含む SELECT ステートメントでは使用できません。
IGNORE_CONSTRAINTS
INSERT ステートメントで、BULK オプションが OPENROWSET と一緒に使用されているときにのみ適用できます。テーブルに対する制約を一括インポート操作時に無視することを指定します。既定では、INSERT によって CHECK 制約および FOREIGN KEY 制約がチェックされます。一括インポート操作の際に 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」を参照してください。
- NOWAIT
テーブルでロックがかかったらすぐにメッセージを返すように SQL Server 2005 データベース エンジンを設定します。NOWAIT は、特定のテーブルに SET LOCK_TIMEOUT 0 を指定することに相当します。
- PAGLOCK
通常使用される行やキーに対する個々のロックまたは単一のテーブル ロックの代わりに、ページ ロックを使用します。既定では、操作に適したロック モードを使用します。SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定しても、UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定しない限り、ページ ロックは取得されません。
- READCOMMITTED
読み取り操作が、ロックまたは行バージョンを使用して、READ COMMITTED 分離レベルのルールに従うことを指定します。データベース オプション READ_COMITTED_SNAPSHOT が OFF の場合、データベース エンジンはデータの読み取り時に共有ロックを取得し、読み取り操作が完了するとロックを解除します。データベース オプション READ_COMITTED_SNAPSHOT が ON の場合、データベース エンジンはロックを取得せずに行バージョンを使用します。分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。
- READCOMMITTEDLOCK
読み取り操作が、ロックを使用して、READ COMMITTED 分離レベルのルールに従うことを指定します。READ_COMMITTED_SNAPSHOT データベース オプションの設定にかかわらず、データベース エンジンはデータの読み取り時に共有ロックを取得し、読み取り操作が完了するとロックを解除します。分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。
READPAST
他のトランザクションによってロックされている行を、データベース エンジンが読み取らないことを指定します。多くの場合、この指定はページにも適用されます。データベース エンジンは、ロックが解除されるまで現在のトランザクションをブロックする代わりに、行やページをスキップします。READPAST は、READ COMMITTED 分離レベルまたは REPEATABLE READ 分離レベルで実行中のトランザクションでのみ指定できます。SNAPSHOT 分離レベルで実行中のトランザクションにおいてこのオプションを指定する場合、UPDLOCK や HOLDLOCK など、ロックが必要な他のテーブル ヒントと組み合わせて指定する必要があります。READPAST を指定すると、行レベルとページ レベルの両方のロックがスキップされます。READPAST は、UPDATE ステートメントまたは DELETE ステートメントで参照されるテーブル、および FROM 句で参照されるテーブルで指定できます。UPDATE ステートメントで READPAST を指定した場合、ステートメント内での指定場所にかかわらず、更新対象データ特定のためのデータ読み取り時にだけ適用されます。INSERT ステートメントの INTO 句では、テーブルに READPAST を指定することができません。READPAST を使用する読み取り操作はブロックを行いません。READPAST を使用する更新操作や削除操作は、外部キーやインデックス付きビューの読み取り時、またはセカンダリ インデックスの変更時にブロックを行う場合があります。
たとえば、テーブル T1 に整数型の列が 1 つあり、値 1、2、3、4、5 が格納されているとします。このテーブルに対してトランザクション A で値 3 を 8 に変更し、この変更をまだコミットしていない間に SELECT * FROM T1 (READPAST) を実行すると、取得される値は 1、2、4、5 となります。READPAST は主に、SQL Server テーブルを使用する作業キューの実装時に、ロックの競合を減らすために使用します。READPAST を使用するキュー リーダーは、他のトランザクションによってロックされたキュー エントリを、ロックが解除されるまで待たずにスキップして、次に使用可能なキュー エントリへ進みます。
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 ヒントの使用は、将来のバージョンの Microsoft SQL Server でサポートされなくなる予定です。新しい開発作業ではこのコンテキストでのヒントの使用は避け、現在このヒントを使用しているアプリケーションは変更を検討してください。 SQL Server 2005 では、次のいずれかを使用することによって、ロックの競合を最小限に抑えながら、コミットされていないデータ変更のダーティ リードからトランザクションを保護することができます。
- 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 など、ロックが必要な他のテーブル ヒントと組み合わせて指定しない限り、行ロックは取得されません。
- SERIALIZABLE
HOLDLOCK に相当します。共有ロックがより制限的になります。テーブルまたはデータ ページが不要になったときに、トランザクションが完了しているかどうかにかかわらず共有ロックが解除されるのではなく、共有ロックはトランザクションが完了するまで保持されます。SERIALIZABLE 分離レベルで実行しているトランザクションと同じセマンティクスで、スキャンが実行されます。分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。
TABLOCK
テーブルにロックを使用し、ステートメント終了まで保持することを指定します。データの読み取り中は、共有ロックが使用されます。データの変更中は、排他ロックが使用されます。HOLDLOCK も指定してある場合は、共有テーブル ロックがトランザクション終了まで保持されます。インデックスのないテーブルにデータをインポートするため、OPENROWSET 一括行セット プロバイダで TABLOCK を使用すると、対象テーブルへのデータ読み込みを、ログ記録とロックとを最適化して、複数のクライアントで同時に行うことができます。
- TABLOCKX
トランザクションが完了するまでテーブルに排他ロックを使用することを指定します。
- UPDLOCK
更新ロックを使用することと、これをトランザクション終了まで保持することを指定します。
- XLOCK
排他ロックを使用することと、これをトランザクション終了まで保持することを指定します。ROWLOCK、PAGLOCK、または TABLOCK と組み合わせて指定すると、排他ロックは適切な粒度レベルに適用されます。
解説
テーブルがクエリ プランによってアクセスされているのではない場合、テーブル ヒントは無視されます。これは、オプティマイザがテーブルにまったくアクセスしないことを選択した結果であるか、またはインデックス付きビューが代わりにアクセスされるためである可能性があります。後者の場合、OPTION (EXPAND VIEWS) クエリ ヒントを使用することで、インデックス付きビューへのアクセスを防ぐことができます。
テーブル ヒント間のコンマは省略できますが、できる限り使用するようにしてください。ヒントの分割にコンマの代わりにスペースを用いる方法は、旧バージョンとの互換性を維持するためにサポートされています。
SQL Server 2005 では、一部の例外を除いて、FROM 句でのテーブル ヒントは WITH キーワードと一緒に指定された場合にのみサポートされます。また、テーブル ヒントはかっこを使用して指定する必要があります。
WITH キーワードの有無にかかわらず使用できるテーブル ヒントは、NOLOCK、READUNCOMMITTED、UPDLOCK、REPEATABLEREAD、SERIALIZABLE、READCOMMITTED、FASTFIRSTROW、TABLOCK、TABLOCKX、PAGLOCK、ROWLOCK、NOWAIT、READPAST、XLOCK、および NOEXPAND です。これらのテーブル ヒントを WITH キーワードを使用せずに指定するときは、単独で指定してください。次に例を示します。
FROM t (FASTFIRSTROW)
ヒントを他のオプションと一緒に指定する場合は、次のように WITH キーワードを使用して指定する必要があります。
FROM t WITH (FASTFIRSTROW, INDEX(myindex))
この制限は、互換性レベル 90 のデータベースに対するクエリでヒントを使用する場合に適用されます。
SQL Server 2005 では、すべてのロック ヒントが、ビューで参照されているすべてのテーブルおよびビューに反映されます。また、SQL Server は、対応するロックの一貫性チェックを実行します。
行レベルのロックを取得するロック ヒント ROWLOCK、UPDLOCK、および XLOCK では、実際のデータ行ではなくインデックス キーに対してロックが実行される場合があります。たとえば、テーブルに非クラスタ化インデックスがあり、ロック ヒントを使用する SELECT ステートメントがカバーするインデックスによって処理される場合、ベース テーブルのデータ行ではなく、カバーするインデックスのインデックス キーに対してロックが取得されます。
テーブルに計算列があり、その計算列が、別のテーブル内の列にアクセスする式や関数によって計算される場合、そのテーブル上でテーブル ヒントが使用されることはありません。つまり、テーブル ヒントは反映されません。たとえば、クエリ内のテーブルに NOLOCK テーブル ヒントが指定されているものとします。このテーブルには、別のテーブル内の列にアクセスする式と関数の組み合わせで計算される、計算列があります。式と関数で参照されるテーブルが、アクセスされるときに NOLOCK テーブル ヒントを使用することはありません。
SQL Server では、FROM 句内の各テーブルに対して、次の各グループには複数のテーブル ヒントは許可されません。
- 粒度ヒント : PAGLOCK、NOLOCK、ROWLOCK、TABLOCK、TABLOCKX
- 分離レベル ヒント : HOLDLOCK、NOLOCK、READCOMMITTED、REPEATABLEREAD、SERIALIZABLE
NOEXPAND の使用
NOEXPAND はインデックス付きビューにのみ適用できます。インデックス付きビューとは、一意なクラスタ化インデックスが作成されているビューを示します。インデックス付きビューおよびベース テーブルの両方に存在する列への参照がクエリに含まれていて、クエリ オプティマイザがクエリの実行にインデックス付きビューを使用する方が最適であると判断した場合、クエリ オプティマイザはビューのインデックスを利用します。この機能は、インデックス付きビューのマッチング と呼ばれ、SQL Server 2005 の Enterprise Edition および Developer Edition でのみサポートされています。
ただし、オプティマイザで、インデックス付きビューのマッチングを検討したり、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 2005 では、FROM 句で直接ビューを指定していないクエリで、特定のインデックス付きビューが使用されるようにするヒントは用意されていません。しかし、クエリ オプティマイザでは、インデックス付きビューがクエリで直接参照されていなくても、その使用が検討されます。
詳細については、「ビューのインデックスの解決」を参照してください。
権限
KEEPIDENTITY、IGNORE_CONSTRAINTS、IGNORE_TRIGGERS の各ヒントには、テーブルに対する ALTER 権限が必要です。
例
次の例では、Production.Product
テーブルに対して共有ロックを使用することと、このロックを UPDATE
ステートメントの終了まで保持することを指定します。
UPDATE Production.Product
WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%'
参照
関連項目
OPENROWSET (Transact-SQL)
ヒント (Transact-SQL)
その他の技術情報
ヘルプおよび情報
変更履歴
リリース | 履歴 |
---|---|
2006 年 12 月 12 日 |
|
2006 年 4 月 14 日 |
|
2005 年 12 月 5 日 |
|