SQL ServerとOracleを使用しています。おそらくいくつかの例外がありますが、それらのプラットフォームの一般的な答えは、データとインデックスが同時に更新されるということです。
トランザクションを所有するセッションと他のセッションでインデックスが更新されるタイミングを区別すると役立つと思います。デフォルトでは、トランザクションがコミットされるまで、他のセッションには更新されたインデックスが表示されません。ただし、トランザクションを所有するセッションには、更新されたインデックスがすぐに表示されます。
それについて考える1つの方法として、主キーを持つテーブルを検討してください。SQL ServerおよびOracleでは、これはインデックスとして実装されます。ほとんどの場合INSERT
、主キーに違反するような処理が行われるとすぐにエラーが発生します。そのためには、データと同時にインデックスを更新する必要があります。Postgresなどの他のプラットフォームでは、トランザクションがコミットされたときにのみチェックされる遅延制約が許可されることに注意してください。
次に、一般的なケースを示す簡単なOracleデモを示します。
CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));
INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit
2番目のINSERT
ステートメントはエラーをスローします。
SQLエラー:ORA-00001:一意制約(XXXXXX.SYS_C00384850)違反
00001.
00000-"一意の制約(%s。%s)に違反しています"
*原因:UPDATEまたはINSERTステートメントが重複キーを挿入しようとしました。DBMS MACモードで構成されたTrusted Oracleの場合、重複するエントリが別のレベルに存在すると、このメッセージが表示されることがあります。
*アクション:一意の制限を削除するか、キーを挿入しないでください。
以下のインデックス更新アクションを見たい場合は、SQL Serverの簡単なデモです。まず、100万行と列の非クラスター化インデックスを含む2列のテーブルを作成しVAL
ます。
DROP TABLE IF EXISTS X_TABLE_IX;
CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);
CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);
-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);
次のクエリは非クラスタ化インデックスを使用できます。これは、インデックスがそのクエリのカバーインデックスであるためです。実行に必要なすべてのデータが含まれています。予想どおり、返品は返されません。
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
次に、トランザクションを開始VAL
して、テーブルのほとんどすべての行を更新します。
BEGIN TRANSACTION
UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;
以下はそのためのクエリプランの一部です。
赤で囲まれた部分は、非クラスター化インデックスの更新です。青色で囲まれているのは、本質的にテーブルのデータであるクラスター化インデックスの更新です。トランザクションがコミットされていなくても、クエリの実行の一部でデータとインデックスが更新されていることがわかります。関連するデータのサイズとその他の要因によっては、これが計画に常に表示されるわけではないことに注意してください。
トランザクションがまだコミットされていない状態でSELECT
、上からクエリをもう一度見てみましょう。
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
クエリオプティマイザーは引き続きインデックスを使用でき、今回は999999行が返されると推定します。クエリを実行すると、予期した結果が返されます。
これは簡単なデモでしたが、うまくいけば、少しはうまくいきました。
余談ですが、インデックスがすぐに更新されないと主張される可能性のあるいくつかのケースを知っています。これはパフォーマンス上の理由で行われ、エンドユーザーは一貫性のないデータを見ることができないはずです。たとえば、SQL Serverのインデックスに削除が完全に適用されない場合があります。バックグラウンドプロセスが実行され、最終的にデータがクリーンアップされます。興味があれば、ゴーストレコードについて読むことができます。