次の方法で共有


テーブル ヒント (Transact-SQL)

適用対象: SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceMicrosoft Fabric SQL Database

テーブル ヒントは、データ操作言語 (DML) ステートメントの実行中、クエリ オプティマイザーの既定の動作をオーバーライドするために使用されます。 ロック方法、1 つ以上のインデックス、クエリ処理操作 (テーブル スキャンやインデックス シークなど)、その他のオプションを指定できます。 テーブル ヒントは DML ステートメントの FROM 句で指定され、その句で参照されているテーブルまたはビューにのみ影響します。

注意事項

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

適用対象:

Transact-SQL 構文表記規則

構文

WITH  ( <table_hint> [ [ , ] ...n ] )

<table_hint> ::=
{ NOEXPAND
  | INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
  | FORCESEEK [ ( <index_value> ( <index_column_name> [ , ... ] ) ) ]
  | FORCESCAN
  | HOLDLOCK
  | NOLOCK
  | NOWAIT
  | PAGLOCK
  | READCOMMITTED
  | READCOMMITTEDLOCK
  | READPAST
  | READUNCOMMITTED
  | REPEATABLEREAD
  | ROWLOCK
  | SERIALIZABLE
  | SNAPSHOT
  | SPATIAL_WINDOW_MAX_CELLS = <integer_value>
  | TABLOCK
  | TABLOCKX
  | UPDLOCK
  | XLOCK
}

<table_hint_limited> ::=
{
    KEEPIDENTITY
  | KEEPDEFAULTS
  | HOLDLOCK
  | IGNORE_CONSTRAINTS
  | IGNORE_TRIGGERS
  | NOLOCK
  | NOWAIT
  | PAGLOCK
  | READCOMMITTED
  | READCOMMITTEDLOCK
  | READPAST
  | REPEATABLEREAD
  | ROWLOCK
  | SERIALIZABLE
  | SNAPSHOT
  | TABLOCK
  | TABLOCKX
  | UPDLOCK
  | XLOCK
}

引数

WITH ( <table_hint> ) [ [ , ] ...n ]

一部の例外では、WITH キーワードでヒントが指定されている場合にのみ、FROM 句でテーブル ヒントがサポートされます。 また、テーブル ヒントはかっこを使用して指定する必要があります。

重要

WITH キーワードを省略することは非推奨の機能です。この機能は、今後のバージョンの SQL Server で削除される予定です。 新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションは修正することを検討してください。

次のテーブル ヒントは、WITH キーワードの有無にかかわらず許可されます: NOLOCKREADUNCOMMITTEDUPDLOCKREPEATABLEREADSERIALIZABLEREADCOMMITTEDTABLOCKTABLOCKXPAGLOCKROWLOCKNOWAITREADPASTXLOCKSNAPSHOT、および NOEXPANDWITH キーワードを使用せずにこれらのテーブル ヒントを指定する場合、ヒントは単独で指定する必要があります。 次に例を示します。

FROM t (TABLOCK)

ヒントを別のオプションで指定する場合は、WITH キーワードを使用してヒントを指定する必要があります。

FROM t WITH (TABLOCK, INDEX(myindex))

複数のテーブル ヒント間にはコンマを使用することをお勧めします。

重要

コンマではなくスペースでヒントを区切ることは非推奨の機能です。この機能は、今後のバージョンの SQL Server で削除される予定です。 新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションは修正することを検討してください。

NOEXPAND

クエリ オプティマイザーがクエリを処理するときに、基になるテーブルにアクセスするためにインデックス付きビューを展開しないことを指定します。 クエリ オプティマイザーは、ビューをクラスター化インデックスを持つテーブルのように取り扱います。 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 データベース エンジンによってすべてのインデックス付き列が取得された後、フェッチを実行して残りの列が取得されます。

Note

複数のインデックスを参照するインデックス ヒントが、スター結合のファクト テーブルで使用されている場合、オプティマイザーはそのインデックス ヒントを無視し、警告メッセージを返します。 また、インデックス ヒントが指定されたテーブルでは、インデックス ORing は許可されません。

テーブル ヒント内のインデックスの最大個数は、非クラスター化インデックスが 250 個です。

KEEPIDENTITY

OPENROWSETで オプションを使用する場合は、 ステートメント 適用されます。

インポートしたデータ ファイルの ID 値 (複数可) を ID 列に使用することを指定します。 KEEPIDENTITY 指定されていない場合、この列の ID 値は検証されますがインポートされません。クエリ オプティマイザーは、テーブルの作成時に指定されたシード値と増分値に基づいて一意の値を自動的に割り当てます。

重要

データ ファイルにテーブルまたはビューの ID 列の値が含まれていない場合、ID 列がテーブルの最後の列でない場合は、ID 列をスキップする必要があります。 詳細については、「フォーマット ファイルを使用してデータ フィールド (SQL Server)をスキップする」を参照してください。 ID 列のスキップに成功すると、クエリ オプティマイザーは、その ID 列の一意な値を、インポートされたテーブル行に自動的に割り当てます。

INSERT ... SELECT * FROM OPENROWSET(BULK...) ステートメントでこのヒントを使用する例については、「データの一括インポート時に ID 値を保持する (SQL Server)を参照してください。

テーブルの ID 値の確認については、DBCC CHECKIDENT参照してください。

KEEPDEFAULTS

OPENROWSETで オプションを使用する場合は、 ステートメント 適用されます。

データ レコードに列の値がない場合に NULL ではなく、テーブル列の既定値 (存在する場合) の挿入を指定します。

INSERT ... SELECT * FROM OPENROWSET(BULK...) ステートメントでこのヒントを使用する例については、「一括インポート (SQL Server)中に null または既定値を保持する」を参照してください。

FORCESEEK [ ( <index_value> ( <index_column_name> [ , ...n ] ) ) ]

クエリ オプティマイザーで、テーブルまたはビュー内のデータへのアクセス パスとしてインデックス シーク操作のみを使用するように指定します。

Note

SQL Server 2008 R2 (10.50.x) Service Pack 1 以降では、インデックス パラメーターも指定できます。 その場合、一度でも指定されたインデックス列が使用されると、クエリ オプティマイザーでは指定されたインデックスを介したインデックスのシーク操作のみが検討されます。

  • index_value

    インデックス名またはインデックス ID 値。 インデックス ID 0 (ヒープ) は指定できません。 インデックスの名前または ID を返すには、sys.indexes カタログ ビューにクエリを実行します。

  • index_column_name

    シーク操作に含めるインデックス列の名前。 インデックス パラメーターと共に FORCESEEK を指定することは、FORCESEEK ヒントと共に INDEX を使用することと同じです。 ただし、シーク対象のインデックスとシーク操作で考慮するインデックス列の両方を指定することで、クエリ オプティマイザーで使用されるアクセス パスをより詳細に制御できるようになります。 オプティマイザーでは、必要に応じてさらに多くの列が考慮される場合があります。 たとえば、非クラスター化インデックスが指定されている場合、オプティマイザーは、指定した列に加えてクラスター化インデックス キー列を使用することを選択できます。

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 を指定する場合、次のガイドラインと制限が適用されます。

  • ヒントは、INSERTUPDATE、または DELETE ステートメントのターゲットであるテーブルに対して指定できません。
  • このヒントを INDEX ヒントまたは別の FORCESEEK ヒントと組み合わせて指定することはできません。
  • 少なくとも 1 列を指定する必要があり、先頭のキー列にする必要があります。
  • 追加のインデックス列を指定できますが、キー列を省略することはできません。 たとえば、指定されたインデックスに ab、および c というキー列が含まれている場合、有効な構文には FORCESEEK (MyIndex (a)) および FORCESEEK (MyIndex (a, b) が含まれます。 無効な構文には、FORCESEEK (MyIndex (c))FORCESEEK (MyIndex (a, c) が含まれます。
  • ヒントで指定された列名の順序は、参照先のインデックスでの列の順序と一致させる必要があります。
  • インデックス キーの定義にない列を指定することはできません。 たとえば、非クラスター化インデックスでは、定義されたインデックス キー列のみを指定できます。 インデックスに自動的に含まれるクラスター化キー列は指定できませんが、オプティマイザーによって使用される可能性があります。
  • xVelocity メモリ最適化列ストア インデックスをインデックス パラメーターとして指定することはできません。 エラー 366 が返されます。
  • インデックス定義を変更する (列の追加や削除など) には、そのインデックスを参照するクエリの変更が必要になる場合があります。
  • ヒントを使用すると、オプティマイザーでは、テーブル上の空間インデックスまたは XML インデックスが検討されなくなります。
  • このヒントを FORCESCAN ヒントと組み合わせて指定することはできません。
  • パーティション インデックスの場合、SQL Server によって暗黙的に追加されたパーティション分割列を FORCESEEK ヒントで指定することはできません。

注意事項

パラメーターと共に FORCESEEK を指定すると、オプティマイザーが考慮することができるプランの数が、パラメーターなしで FORCESEEK を指定した場合よりも制限されます。 これにより、より多くの場合に Plan cannot be generated エラーが発生する可能性があります。

FORCESCAN

適用対象: SQL Server 2008 R2 (10.50.x) Service Pack 1 以降のバージョン

クエリ・オプティマイザーが、参照されるテーブルまたはビューへのアクセス・パスとしてインデックス・スキャン操作のみを使用することを指定します。 FORCESCAN ヒントは、オプティマイザーが影響を受ける行数を過小評価し、スキャン操作ではなくシーク操作を選択するクエリに役立ちます。 この場合、操作に許可されるメモリの量が少なすぎて、クエリのパフォーマンスに影響します。

FORCESCAN を指定する際には、INDEX ヒントを使用してもしなくてもかまいません。 インデックス ヒント (INDEX = index_name, FORCESCAN) と組み合わせると、クエリ オプティマイザーは、参照先テーブルにアクセスするときに、指定したインデックスを介してアクセス パスのみをスキャンすると見なされます。 FORCESCANをインデックス ヒント INDEX(0) 共に指定すると、ベース テーブルに対するテーブル スキャン操作を強制できます。

パーティション テーブルとパーティション インデックスの場合、FORCESCAN は、クエリ述語の評価によってパーティションが削除された後に適用されます。 つまり、スキャンは、テーブル全体ではなく、残りのパーティションのみに適用されます。

FORCESCAN ヒントには、次の制限があります。

  • ヒントは、INSERTUPDATE、または DELETE ステートメントのターゲットであるテーブルに対して指定できません。
  • このヒントを複数のインデックス ヒントと共に使用することはできません。
  • このヒントを使用すると、クエリ オプティマイザーで、テーブル上の空間インデックスまたは XML インデックスが考慮されなくなります。
  • このヒントは、リモート データ ソースには指定できません。
  • このヒントを FORCESEEK ヒントと組み合わせて指定することはできません。

HOLDLOCK

これは、SERIALIZABLE に相当します。 詳細については、この記事で後述 SERIALIZABLE を参照してください。 HOLDLOCK は、指定されたテーブルまたはビューにのみ適用され、使用されているステートメントによって定義されたトランザクションの期間のみ適用されます。 HOLDLOCK は、FOR BROWSE オプションを含む SELECT ステートメントでは使用できません。

IGNORE_CONSTRAINTS

OPENROWSETで オプションを使用する場合は、 ステートメント 適用されます。

一括インポート操作でテーブルの制約が無視されることを指定します。 既定では、 は一意の制約 チェックし、主キー制約と外部キー制約 および 制約を確認します。 一括インポート操作に IGNORE_CONSTRAINTS が指定されている場合、INSERT はターゲット テーブルに対するこれらの制約を無視する必要があります。 UNIQUEPRIMARY 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

OPENROWSETで オプションを使用する場合は、 ステートメント 適用されます。

テーブルに対して定義されたトリガーを、一括インポート操作時に無視することを指定します。 既定では、INSERT はトリガーを適用します。

アプリケーションがトリガーに依存せず、パフォーマンスを最大化することが重要な場合にのみ、IGNORE_TRIGGERS を使用します。

NOLOCK

これは、READUNCOMMITTED に相当します。 詳細については、この記事で後述 READUNCOMMITTED を参照してください。

Note

UPDATE または DELETE ステートメントの場合: この機能は、今後のバージョンの SQL Server で削除される予定です。 新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションは修正することを検討してください。

NOWAIT

テーブルでロックがかかったらすぐにメッセージを返すようにデータベース エンジンを設定します。 NOWAIT は、特定のテーブルに SET LOCK_TIMEOUT 0 を指定することと同じです。 NOWAIT ヒントも含まれている場合、TABLOCK ヒントは機能しません。 TABLOCK ヒントを使用している場合に待機しないでクエリを終了するには、代わりにクエリの前に SET LOCK_TIMEOUT 0; を指定します。

PAGLOCK

通常使用される行やキーに対する個々のロックまたは単一のテーブル ロックの代わりに、ページ ロックを使用します。 既定では、操作に適したロック モードを使用します。 SNAPSHOT 分離レベルで動作するトランザクションで PAGLOCK を指定する場合、ロックを必要とする他のテーブル ヒント (UPDLOCKHOLDLOCK など) と組み合わせて指定しない限り、ページ ロックは取得されません。

READCOMMITTED

読み取り操作が、ロックまたは行のバージョン管理を使用して、READ COMMITTED 分離レベルの規則に準拠することを指定します。 データベース オプション READ_COMMITTED_SNAPSHOTOFFされている場合、データベース エンジンは、データの読み取り時に共有ロックを取得し、読み取り操作が完了したときにそれらのロックを解放します。 データベース オプション READ_COMMITTED_SNAPSHOTONされている場合、データベース エンジンはロックを取得せず、行のバージョン管理を使用します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVELを参照してください。

Note

UPDATE または DELETE ステートメントの場合: この機能は、今後のバージョンの SQL Server で削除される予定です。 新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションは修正することを検討してください。

READCOMMITTEDLOCK

読み取り操作が、ロックを使用して READ COMMITTED 分離レベルの規則に準拠することを指定します。 READ_COMMITTED_SNAPSHOT データベース オプションの設定にかかわらず、データベース エンジンでは、データの読み取り時に共有ロックを獲得し、読み取り操作が完了するとそれらのロックを解放します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVELを参照してください。 このヒントは、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 は、データを読み取って更新するレコードを識別する場合にのみ適用されます。これは、ステートメント内の指定場所に関係なくです。 READPAST ステートメントの INTO 句のテーブルに対 INSERT して指定することはできません。 外部キーまたはインデックス付きビューの読み取り時、またはセカンダリ インデックスの変更時に、READPAST を使用する更新操作または削除操作がブロックされることがあります。

READPAST は、READ COMMITTED または REPEATABLE READ 分離レベルで動作するトランザクションでのみ指定できます。 SNAPSHOT 分離レベルで動作するトランザクションで READPAST を指定する場合、ロックを必要とする他のテーブル ヒント (UPDLOCKHOLDLOCK など) と組み合わせて指定する必要があります。

READ_COMMITTED_SNAPSHOT データベース オプションが ON に設定されていて、次のいずれかの条件に該当する場合、READPAST テーブル ヒントを指定することはできません。

  • セッションのトランザクション分離レベルは READ COMMITTED
  • クエリで READCOMMITTED テーブル ヒントも指定されている。

このような場合に READPAST ヒントを指定するには、READCOMMITTED テーブル ヒントがあればそれを削除し、クエリに READCOMMITTEDLOCK テーブル ヒントを含めます。

READUNCOMMITTED

ダーティ リードを許可することを指定します。 現在のトランザクションによって読み取られたデータが、他のトランザクションによって変更されるのを防ぐために、共有ロックは発行されません。また、他のトランザクションによって排他ロックが設定されていても、ロックされたデータを現在のトランザクションで読み取ることはブロックされません。 ダーティ リードを許可するとコンカレンシーが高まりますが、他のトランザクションによってロールバックされているデータ変更を読み取る可能性があります。 これにより、トランザクションのエラーが発生したり、コミットされなかったデータがユーザーに表示されたり、ユーザーにレコードが 2 回表示されたりする可能性があります (またはまったく表示されません)。

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 ヒントを無視します。

Note

UPDATE ステートメントまたは DELETE ステートメントのターゲット テーブルに適用される FROM 句の READUNCOMMITTED および NOLOCK ヒントの使用は、今後のバージョンの SQL Server で削除される予定です。 新しい開発作業ではこのコンテキストでのヒントの使用を避け、現在このヒントを使用しているアプリケーションは変更を検討してください。

次のいずれかのオプションを使用して、コミットされていないデータ変更のダーティ読み取りからトランザクションを保護しながら、ロックの競合を最小限に抑えることができます。

  • READ_COMMITTED_SNAPSHOT データベース オプションが ONに設定された READ COMMITTED 分離レベル。
  • SNAPSHOT 分離レベル。

分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVELを参照してください。

Note

READUNCOMMITTED が指定されたときに エラー メッセージ 601 が表示される場合は、デッドロック エラー (エラー メッセージ 1205) と同じように解決し、ステートメントを再試行してください。

REPEATABLEREAD

分離レベルで実行されているトランザクションと同じロック セマンティクスでスキャン REPEATABLE READ 実行することを指定します。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVELを参照してください。

ROWLOCK

通常取得されるページ ロックまたはテーブル ロックの代わりに、行ロックを取得することを指定します。 SNAPSHOT 分離レベルで動作するトランザクションで ROWLOCK を指定する場合、ロックを必要とする他のテーブル ヒント (UPDLOCKHOLDLOCK など) と組み合わせて指定しない限り、行ロックは取得されません。 クラスター化された列ストア インデックスのあるテーブルでは、ROWLOCK を使用することはできません。 次の例では、アプリケーションにエラー 651 が返されます。

UPDATE [dbo].[FactResellerSalesXL_CCI] WITH (ROWLOCK)
    SET UnitPrice = 50
WHERE ProductKey = 150;

SERIALIZABLE

これは、HOLDLOCK に相当します。 共有ロックがより制限的になります。テーブルまたはデータ ページが不要になったときに、トランザクションが完了しているかどうかにかかわらず共有ロックが解除されるのではなく、共有ロックはトランザクションが完了するまで保持されます。 スキャンは、SERIALIZABLE 分離レベルで実行されるトランザクションと同じセマンティクスで実行されます。 分離レベルの詳細については、「SET TRANSACTION ISOLATION LEVELを参照してください。

SNAPSHOT

適用対象: SQL Server 2014 (12.x) 以降のバージョン

メモリ最適化されたテーブルは、SNAPSHOT 分離でアクセスされます。 次の例で示すように、SNAPSHOT は、メモリ最適化テーブルのみで使用できます (ディスク ベースのテーブルでは使用できません)。 詳細については、「メモリ最適化テーブルの概要」を参照してください。

SELECT *
FROM dbo.Customers AS c WITH (SNAPSHOT)
     LEFT OUTER JOIN dbo.[Order History] AS oh
         ON c.customer_id = oh.customer_id;

SPATIAL_WINDOW_MAX_CELLS = <integer_value>

適用対象: SQL Server 2012 (11.x) 以降のバージョン

geometry オブジェクトや geography オブジェクトのテセレーションに使用するセルの最大数を指定します。 <integer_value> は、1 - 8192 の整数値です。

このオプションを使用すると、プライマリとセカンダリのフィルターの実行時間の間のトレードオフを調整することによって、クエリの実行時間を微調整できます。 値を大きくすると、セカンダリ フィルターの実行時間が短縮されますが、プライマリ フィルターの実行時間が増加します。値を小さくすると、プライマリ フィルターの実行時間が短縮されますが、セカンダリ フィルターの実行時間が増加します。 密度の高い空間データの場合は、大きい値を指定して、プライマリ フィルターでより適切な近似値を提供し、セカンダリ フィルターの実行時間を減少させることで、実行時間を短縮させます。 密度の低いデータの場合は、小さい値を指定して、プライマリ フィルターの実行時間を短縮します。

このオプションは、手動と自動の両方のグリッド テセレーションに使用できます。

TABLOCK

取得したロックがテーブル レベルで適用されることを指定します。 取得されるロックの種類は、実行されるステートメントによって異なります。 たとえば、SELECT ステートメントは共有ロックを取得できます。 TABLOCK を指定することで、共有ロックが、行またはページ レベルではなくテーブル全体に適用されます。 HOLDLOCK も指定されている場合、テーブル ロックはトランザクションが終了するまで保持されます。

INSERT INTO <target_table> SELECT <columns> FROM <source_table> ステートメントを使用してデータをヒープにインポートする場合、ターゲット テーブルに対して TABLOCK ヒントを指定すると、そのステートメントに対して最小限のログと最適なロックを有効にすることができます。 データベース復旧モデルが単純復旧モデルまたは一括ログ復旧モデルに設定されている必要もあります。 TABLOCK ヒントを使用すると、ヒープまたはクラスター化列ストア インデックスに対する並列挿入も有効になります。 詳細については、「INSERT参照してください。

テーブルにデータをインポートするため、OPENROWSET 一括行セット プロバイダーで TABLOCK を使用すると、ログとロックを最適化して、ターゲット テーブルへのデータの読み込みを複数のクライアントで同時に行うことができます。 詳細については、「一括インポートでの最小ログ記録の前提条件を する」を参照してください。

TABLOCKX

テーブルに排他ロックを使用することを指定します。

UPDLOCK

更新ロックを使用することと、これをトランザクション終了まで保持することを指定します。 UPDLOCK を使用すると、行レベルまたはページ レベルの読み取り操作に対してのみ更新ロックが適用されます。 UPDLOCKTABLOCK と組み合わせるか、なんらかの理由でテーブル レベルのロックを取得すると、代わりに排他 (X) ロックが取得されます。

UPDLOCK を指定すると、READCOMMITTED および READCOMMITTEDLOCK 分離レベルのヒントは無視されます。 たとえば、セッションの分離レベルを SERIALIZABLE に設定し、クエリで (UPDLOCKREADCOMMITTED) を指定すると、READCOMMITTED ヒントは無視され、トランザクションは SERIALIZABLE 分離レベルを使用して実行されます。

XLOCK

排他ロックを使用することと、これをトランザクション終了まで保持することを指定します。 ROWLOCKPAGLOCK、または TABLOCK と組み合わせて指定すると、排他ロックは適切な粒度レベルに適用されます。

注釈

テーブルがクエリ プランによってアクセスされない場合、テーブル ヒントは無視されます。 これは、オプティマイザーがテーブルにまったくアクセスしないことを選択したか、代わりにインデックス付きビューにアクセスすることが原因で発生する可能性があります。 後者の場合は、OPTION (EXPAND VIEWS) クエリ ヒントを使用してインデックス付きビューにアクセスできないようにできます。

すべてのロック ヒントが、クエリ プランによってアクセスされているすべてのテーブルおよびビュー (ビューで参照されているテーブルおよびビューを含む) に反映されます。 また、SQL Server は、対応するロックの整合性チェックを実行します。

ロック ヒント ROWLOCKUPDLOCK、および行レベルのロックを取得する XLOCK は、実際のデータ行ではなくインデックス キーにロックを設定する場合があります。 たとえば、テーブルに非クラスター化インデックスがあり、ロック ヒントを使用する SELECT ステートメントがカバー インデックスによって処理される場合、ベース テーブルのデータ行ではなく、カバー インデックスのインデックス キーに対してロックが取得されます。

テーブルに計算列が含まれており、その計算列が、別のテーブル内の列にアクセスする式または関数によって計算される場合、テーブル ヒントがそれらのテーブルで使用されたり、反映されたりすることはありません。 たとえば、クエリ内のテーブルに NOLOCK テーブル ヒントが指定されているものとします。 このテーブルには、別のテーブル内の列にアクセスする式と関数の組み合わせで計算される、計算列があります。 式と関数で参照されるテーブルでは、アクセスされるときに NOLOCK テーブル ヒントが使用されることはありません。

SQL Server では、FROM 句の各テーブルに対して、次の各グループから複数のテーブル ヒントを使用することはできません。

  • 粒度ヒント: PAGLOCKNOLOCKREADCOMMITTEDLOCKROWLOCKTABLOCKTABLOCKX
  • 分離レベル ヒント: HOLDLOCKNOLOCKREADCOMMITTEDREPEATABLEREADSERIALIZABLE

フィルター選択されたインデックス ヒント

フィルター選択されたインデックスはテーブル ヒントとして使用できますが、クエリが選択したすべての行をカバーしていない場合、クエリ オプティマイザーによってエラー 8622 が生成されます。 フィルター選択されたインデックス ヒントが無効になる例を次に示します。 この例では、フィルター選択されたインデックス FIBillOfMaterialsWithComponentID を作成し、SELECT ステートメントのインデックス ヒントとして使用します。 フィルター選択されたインデックスの述語には、ComponentID が 533、324、および 753 のデータ行が含まれています。 クエリ述語にも ComponentID が 533、324、753 のデータ行が含まれていますが、ComponentID 855 および 924 も含めるように結果セットが拡張されています。これらは、フィルター選択されたインデックスには含まれていません。 したがって、クエリ オプティマイザーは、フィルター選択されたインデックス ヒントを使用できず、エラー 8622 が生成されます。 詳細については、「フィルター選択されたインデックスを作成する」を参照してください。

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参照してください。

NOEXPAND を使用する

NOEXPAND は、"インデックス付きビュー" にのみ適用されます。 インデックス付きビューとは、一意なクラスター化インデックスが作成されているビューを示します。 インデックス付きビューおよびベース テーブルの両方に存在する列への参照がクエリに含まれていて、クエリ オプティマイザーがクエリの実行にインデックス付きビューを使用する方が最適であると判断した場合、クエリ オプティマイザーはビューのインデックスを利用します。 この機能は、インデックス付きビューのマッチングと呼ばれます。 Sql Server 2016 (13.x) Service Pack 1 より前では、クエリ オプティマイザーによるインデックス付きビューの自動使用は、SQL Server の特定のエディションでのみサポートされています。 SQL Server 2016 (13.x) Service Pack 1 以降のバージョンでは、すべてのエディションでインデックス付きビューの自動使用がサポートされています。 また、Azure SQL Database および Azure SQL Managed Instance では、NOEXPAND ヒントを指定しなくても、インデックス付きビューの自動的な使用もサポートされます。

詳細については、「クエリ処理アーキテクチャ ガイド」を参照してください。

Windows の SQL Server の各エディションでサポートされる機能の一覧については、以下を参照してください。

ただし、クエリ オプティマイザーで一致するインデックス付きビューを検討したり、NOEXPAND ヒントで参照されるインデックス付きビューを使用したりするには、次の SET オプションを ONに設定する必要があります。

  • ANSI_NULLS
  • ANSI_PADDING
  • ANSI_WARNINGS
  • ARITHABORT 1
  • CONCAT_NULL_YIELDS_NULL
  • QUOTED_IDENTIFIER

1ARITHABORT は、ANSI_WARNINGSONに設定されている場合、暗黙的に ON に設定されます。 したがって、この設定を手動で調整する必要はありません。

また、NUMERIC_ROUNDABORT オプションを OFFに設定する必要があります。

クエリ オプティマイザーでインデックス付きビューのインデックスを使用するように強制するには、NOEXPAND オプションを指定します。 このヒントは、ビューがクエリ内でも指定されている場合にのみ使用できます。 SQL Server には、FROM 句でビューに直接名前を付けないクエリで、特定のインデックス付きビューを強制的に使用するためのヒントは用意されていません。 しかし、クエリ オプティマイザーでは、インデックス付きビューがクエリで直接参照されていなくても、その使用が考慮されます。 SQL Server データベース エンジンは、NOEXPAND テーブル ヒントが使用されている場合にのみ、インデックス付きビューに統計を自動的に作成します。 このヒントを省略すると、統計の不足に関する実行プランの警告が発生する可能性があります。これは、統計を手動で作成しても解決することはできません。

クエリの最適化中、データベース エンジンでは、クエリでビューが直接参照されたり、NOEXPAND ヒントが使用されたりするときに、自動的に、または手動で作成されたビュー統計を使用します。

テーブル ヒントをクエリ ヒントとして使用する

テーブル ヒント は、OPTION (TABLE HINT) 句を使用してクエリ ヒントとして指定することもできます。 プラン ガイドのコンテキスト内でのみ、テーブル ヒントをクエリ ヒントとして使用することをお勧めします。 アドホック クエリに対しては、これらのヒントをテーブル ヒントとしてのみ指定します。 詳細については、「クエリ ヒントの」を参照してください。

アクセス許可

KEEPIDENTITYIGNORE_CONSTRAINTS、および IGNORE_TRIGGERS ヒントには、テーブルに対する ALTER 権限が必要です。

A. TABLOCK ヒントを使用してロック手法を指定する

次の例では、AdventureWorks2022 データベースの Production.Product テーブルで共有ロックを取得し、UPDATE ステートメントの最後まで保持することを指定します。

UPDATE Production.Product WITH (TABLOCK)
    SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO

B. FORCESEEK ヒントを使用してインデックス シーク操作を指定する

次の例では、インデックスを指定せずに FORCESEEK ヒントを使用して、クエリ オプティマイザーで AdventureWorks2022 データベースの Sales.SalesOrderDetail テーブルに対するインデックス シーク操作を実行するように強制します。

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 ヒントを使用して、クエリ オプティマイザーで、指定したインデックスおよびインデックス列に対してインデックス シーク操作を実行するように強制します。

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 ヒントを使って、AdventureWorks2022 データベースの Sales.SalesOrderDetail テーブルにスキャン操作を実行するようクエリ オプティマイザーに強制します。

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);