インデックスが一意の値を持つことがわかっている場合、そのように宣言すると、挿入または選択のパフォーマンスにどのような影響がありますか。
インデックスが一意であることをオプティマイザーが認識している場合、それはクエリ プランにどのように影響しますか?
一意性を指定することで整合性を維持できることは理解していますが、その議論はさておき、パフォーマンスへの影響はどうなるでしょうか。
インデックスが一意の値を持つことがわかっている場合、そのように宣言すると、挿入または選択のパフォーマンスにどのような影響がありますか。
インデックスが一意であることをオプティマイザーが認識している場合、それはクエリ プランにどのように影響しますか?
一意性を指定することで整合性を維持できることは理解していますが、その議論はさておき、パフォーマンスへの影響はどうなるでしょうか。
簡単に言うと、データが本質的に である場合、それらにインデックスをUNIQUE
作成することでメリットが得られます。UNIQIE
詳細な説明については、私のブログの記事を参照してください。
さて、悲惨な詳細。
@Mehrdadが言ったようUNIQUENESS
に、プランビルダーの推定行数に影響します。
UNIQUE
index は可能な限り最大の選択性を持っています。それが理由です:
SELECT *
FROM table1 t2, table2 t2
WHERE t1.id = :myid
AND t2.unique_indexed_field = t1.value
ほぼ確実に使用しますNESTED LOOPS
が、
SELECT *
FROM table1 t2, table2 t2
WHERE t1.id = :myid
AND t2.non_unique_indexed_field = t1.value
HASH JOIN
オプティマイザがそれnon_unique_indexed_field
が選択的ではないと判断した場合は、a の恩恵を受ける可能性があります。
インデックスがCLUSTERED
(つまり、行自体がインデックス リーフに含まれている) であり、非UNIQUE
表示の場合、呼び出される特別な隠し列uniquifier
が各インデックス キーに追加されるため、キーが大きくなり、インデックスが遅くなります。
そのため、UNIQUE CLUSTERED
インデックスは実際にはインデックスよりも少し効率的ですnon-UNIQUE CLUSTERED
。
では、呼び出された に対してOracle
結合UNIQUE INDEX
が必要ですkey preservation
。これにより、テーブルの各行が最大 1 回選択され、ビューが更新可能になります。
このクエリ:
UPDATE (
SELECT *
FROM mytable t1, mytable t2
WHERE t2.reference = t1.unique_indexed_field
)
SET value = other_value
で動作しますがOracle
、これは次のとおりです。
UPDATE (
SELECT *
FROM mytable t1, mytable t2
WHERE t2.reference = t1.non_unique_indexed_field
)
SET value = other_value
失敗します。
ただし、これは の問題ではありませんSQL Server
。
もう1つ、このようなテーブルの場合、
CREATE TABLE t_indexer (id INT NOT NULL PRIMARY KEY, uval INT NOT NULL, ival INT NOT NULL)
CREATE UNIQUE INDEX ux_indexer_ux ON t_indexer (uval)
CREATE INDEX ix_indexer_ux ON t_indexer (ival)
、このクエリ:
/* Sorts on the non-unique index first */
SELECT TOP 1 *
FROM t_indexer
ORDER BY
ival, uval
を使用しますがTOP N SORT
、これは次のとおりです。
/* Sorts on the unique index first */
SELECT TOP 1 *
FROM t_indexer
ORDER BY
uval, ival
インデックススキャンのみを使用します。
後者のクエリの場合、は一意ival
であるため、で追加の並べ替えを行っても意味がなく、オプティマイザはこれを考慮します。uval
200,000
行のサンプル データ( id == uval == ival
) では、前者のクエリは15
数秒間実行されますが、後者のクエリは瞬時に実行されます。
もちろん、オプティマイザーは一意性を考慮します。これは、クエリ プランで予想される行数に影響します。
データを挿入すると、パフォーマンスが低下します。一意性を確認する必要があります。
良いテストだと思ったので、100 万行を超える Production テーブルのマシンでこれをテストしました。結果は興味深いものでした。生の数値は次のとおりです。
-- インデックスなし:
Setup Time: 8888, Insert Time: 501690
-- 一意の制約:
Setup Time: 42, Insert Time: 488030
セットアップは、一意の制約を追加するフィールドの最大値を取得することで構成されていたため、論理的には、制約を追加することでパフォーマンスが劇的に向上しました。これにより、この外部キーで検索するときのパフォーマンスも向上します。
興味深いことに、挿入時間もわずかに (2.7228%) 改善されたため、[私のテスト ケースでは] 制約 (+ 固有のインデックス) を追加することによるプラスの影響のみがありました。
テストでは、制約の追加によるプラスの影響のみが示され、パフォーマンスへの影響はありません。
注: 私たちのテスト システムでは、ほとんどの場合、値が一意であると予想されるため、一意でない値の挿入をテストしませんでした。このデータでは、これは本当に例外であり、パフォーマンスが必要なものではありません。
はい、クエリ エンジンによって考慮されます。
おそらくもっと重要なのは、一意性によってデータの整合性が保護されることです。パフォーマンスは、これを無視する理由になります。
パフォーマンスは、プラスまたはマイナスの影響を受けるか、またはまったく影響を受けない可能性があります。インデックスが使用されているかどうかなど、クエリによって異なります。