web-dev-qa-db-ja.com

一意のインデックスの代わりに一意の制約を使用する必要があるのはいつですか?

列に個別の値を設定する場合は、制約を使用することができます

create table t1(
id int primary key,
code varchar(10) unique NULL
);
go

または、一意のインデックスを使用できます

create table t2(
id int primary key,
code varchar(10) NULL
);
go

create unique index I_t2 on t2(code);

一意の制約のある列は、一意のインデックスの候補として適しているようです。

一意の制約を使用し、代わりに一意のインデックスを使用しない既知の理由はありますか?

210
bernd_k

内部では、一意の制約は一意のインデックスと同じ方法で実装されます。制約を適用するための要件を効率的に満たすには、インデックスが必要です。インデックスがUNIQUE制約の結果として作成された場合でも、クエリプランナーは、特定のクエリにアプローチするための最良の方法と見なすと、他のインデックスと同じように使用できます。

したがって、両方の機能をサポートするデータベースの場合、どちらを使用するかの選択は、多くの場合、優先されるスタイルと一貫性に帰着します。

インデックスをインデックスとして使用することを計画している場合(つまり、コードがそのフィールドの検索/並べ替え/フィルタリングに依存している可能性があるため)、制約ではなく明示的に一意のインデックスを使用して(ソースにコメントを付けて)、明確-この方法で、アプリケーションの新しいリビジョンで一意性の要件が変更された場合、一意のインデックスが一意のインデックスの代わりに配置されることを確認します(一意の制約を削除するだけで削除されます)完全にインデックス)。また、特定のインデックスにインデックスヒント(つまり、WITH(INDEX(ix_index_name)))で名前を付けることもできます。これは、一意性を管理するために背後で作成されたインデックスには当てはまらないと考えられます。

同様に、フィールドを検索または並べ替えに使用する必要がなく、一意性をビジネスルールとして適用する必要があるだけの場合は、制約を使用して、他の誰かがテーブル定義を確認するときに目的の使用をより明確にします。

同じフィールドで一意の制約と一意のインデックスの両方を使用すると、データベースが明るくなって複製を確認できないため、余分なスペースを消費し、行の挿入/更新を遅くする2つのインデックスが作成されることに注意してください。

165
David Spillett

他の回答のポイントに加えて、2つの主な違いは次のとおりです。

注:エラーメッセージはSQL Server 2012からのものです。

エラー

一意制約に違反すると、エラー2627が返されます。

Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'P1U_pk'. Cannot insert duplicate key in object 'dbo.P1U'. The duplicate key value is (1).
The statement has been terminated.

一意のインデックスの違反はエラー2601を返します。

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.P1' with unique index 'P1_u'. The duplicate key value is (1).
The statement has been terminated.

無効にする

一意制約を無効にすることはできません。

Msg 11415, Level 16, State 1, Line 1
Object 'P1U_pk' cannot be disabled or enabled. This action applies only to foreign key and check constraints.
Msg 4916, Level 16, State 0, Line 1
Could not enable or disable the constraint. See previous errors.

ただし、主キー制約または一意制約の背後にある一意のインデックスは、一意のインデックスと同様に無効にすることができます。 ハットチップBrain2000

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

クラスタ化インデックスを無効にするとデータにアクセスできなくなるという通常の警告に注意してください。

オプション

一意の制約は、FILLFACTORIGNORE_DUP_KEYなどのインデックスオプションをサポートしますが、これはSQL Serverのすべてのバージョンに当てはまるわけではありません。

含まれる列

非クラスター化インデックスには、インデックス付けされていない列を含めることができます(カバリングインデックスと呼ばれます。これはパフォーマンスの大幅な向上です)。 PRIMARY KEYおよびUNIQUE制約の背後にあるインデックスに列を含めることはできません。 ハットチップ@ypercube。

フィルタリング

一意の制約はフィルタリングできません。

一意のインデックスをフィルタリングできます。

CREATE UNIQUE NONCLUSTERED INDEX Students6_DrivesLicence_u 
ON dbo.Students6( DriversLicenceNo ) WHERE DriversLicenceNo is not null ;

外部キー制約

外部キー制約は、フィルターされていない一意のインデックスを参照できますが、フィルターされた一意のインデックスは参照できません(SQL Server 2005で追加されたと思います)。

ネーミング

制約を作成する場合、制約名の指定はオプションです(5種類の制約すべて)。名前を指定しない場合、MSSQLが名前を生成します。

CREATE TABLE dbo.T1 (
    TID int not null PRIMARY KEY
) ;
GO
CREATE TABLE dbo.T2 (
    TID int not null CONSTRAINT T2_pk PRIMARY KEY
) ;

インデックスを作成するときは、名前を指定する必要があります。

ハットチップ@ i-one。

リンク集

http://technet.Microsoft.com/en-us/library/aa224827(v = SQL.80).aspx

http://technet.Microsoft.com/en-us/library/ms177456.aspx

107

MSDNを信頼できる情報源として引用するには:

UNIQUE制約の作成と制約に依存しない一意のインデックスの作成の間に大きな違いはありません。データの検証は同じ方法で行われ、クエリオプティマイザーは、制約によって作成された、または手動で作成された一意のインデックスを区別しません。ただし、列にUNIQUE制約を作成すると、インデックスの目的が明確になります... 詳細はこちら

そして...

データベースエンジンは自動的にUNIQUEインデックスを作成して、UNIQUE制約の一意性要件を適用します。したがって、重複する行を挿入しようとすると、データベースエンジンは、UNIQUE制約に違反していることを示すエラーメッセージを返し、行をテーブルに追加しません。クラスター化インデックスが明示的に指定されていない限り、一意の非クラスター化インデックスがデフォルトで作成され、UNIQUE制約が適用されます... 詳細はこちら

その他: https://technet.Microsoft.com/en-us/library/aa224827%28v=sql.80%29.aspx

10
user919426

一意制約と一意インデックスの主な違いの1つは、別のテーブルの外部キー制約が、一意制約を構成する列を参照できることです。これは一意のインデックスには当てはまりません。さらに、一意の制約はANSI標準の一部として定義されていますが、インデックスはそうではありません。最後に、一意の制約は、インデックスが物理的な側面である一方で、論理データベース設計(異なるDBエンジンによって異なる方法で実装される可能性がある)の領域に存在すると見なされます。したがって、一意制約はより宣言的です。ほとんどすべての場合で、一意制約を使用します。

7
Dmitry Frenkel

Oracleの大きな違いは、一意の制約では実行できない関数固有のインデックスを作成できることです。

例えば

create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);

そう fk_xyzは、amount != 0

1
Amir Pashazadeh