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


195

列に個別の値が必要な場合は、制約を使用できます

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

一意の制約を持つ列は、一意のインデックスの適切な候補のようです。

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


9
彼らは実際に違いますか?postgresqlなどの一部のデータベースでは、一意の制約が一意のインデックスを作成するだけです。私はSQLサーバーについて何も知らないので答えていません。
xenoterracide

6
postgresqlでは、一意のインデックスでは式を使用できますが、一意の制約では使用できません。
ニールマクギガン

1
MS SQLでも同じように実装されています。同じデータで2つのテーブルを作成してみてください。1つは一意の制約を使用し、もう1つは一意のインデックスを使用します。これらは同じ量のインデックススペースを使用し、どちらも(実際には)作成された一意のインデックスに対してシークできるようになります。
すべての取引のジョン

回答:


153

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

そのため、両方の機能をサポートするデータベースの場合、多くの場合、どちらを使用するかは、好みのスタイルと一貫性に依存します。

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

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

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


1
「データベースが十分に明るくならない」と思っていますか?それはすべてのRDBMSに当てはまりますか?SQL標準によって義務付けられていますか?そして、たとえそうであるとしても(そしてなぜそうあるべきだろうか)、すべての実装はそのように実装しますか?または:なぜDBは十分に「明るく」できないのですか?
ユルゲンA.エアハルト

4
@jae:DBMSは確かに十分に明るい可能性がありますが、各DBMSで確認して確認する必要があります。MSSQLに2つの同一のインデックスを作成するように依頼すると、2つの名前で参照される1つではなく2つのインデックスが作成されます(少なくとも、このような状況を見つけたときは少なくともそうでした(私の側のコピー+貼り付けエラーのため))、そのため、制約のためにインデックスの1つが存在する場合も同様であると思います。
デビッドスピレット

3
+1 @David Spillett基本的にDBMSは、あなたが何をしているのか知っていると仮定していると思います。同じインデックスを2回作成したい場合は、そのことについて疑問はありません。
アンドリューバーバー

2
非常に洞察力に富んでいます。この振る舞いがMySQLとApache Derbyにもあるのか知っていますか?
corsiKa

5
あなたはできる制約に名前を付け、インデックスヒントでそれを使用しています。CREATE TABLE #T(X INT CONSTRAINT PK PRIMARY KEY NONCLUSTERED);SELECT * FROM #T WITH(INDEX(PK)) WHERE X = 1。ただし、制約はINCLUDEd列やフィルター選択されたインデックスなどのすべてのインデックスオプションをサポートしているわけではないため、インデックスはより柔軟になります。
マーティンスミス

101

他の回答のポイントに加えて、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.

ただし、主キー制約または一意制約の背後にある一意のインデックスは、一意のインデックスと同様に無効にできます。Hat-tip Brain2000。

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

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

オプション

一意の制約は、FILLFACTORやなどのインデックスオプションをサポートしIGNORE_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


ユニーク制約は、インデックスと同じ方法で無効および有効にできます。ALTERINDEX tbl ON uconstraint DISABLE、ALTER INDEX tbl ON uconstraint REBUILD
Brain2000

@ Brain2000に感謝します。偶然にも、私はこのコメントを読む直前に、今朝インデックスを無効にするセクションを教えました。
グリーンストーンウォーカー

10

信頼できるソースとしてMSDNを引用するには:

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

そして...

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

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


6

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


8
-1 SQL Serverでは、次の点が間違っています。「別のテーブルの外部キー制約は、一意制約を構成する列を参照できます。これは、一意インデックスには当てはまりません」。SQL Serverでは、FK制約を一意のインデックスに参照できます。
AK

4
外部キー制約が一意のインデックスを参照する機能は、SQL Server 2005に追加されたと思います。BOLの一部のページを含む多くのソースは、変更を反映するように更新されていないため、Dmitryの答えはないと思いますdownvotesに値する。彼の答えの残りはスポットです-制約はANSI標準ですが、インデックスはそうではありません。
グリーンストーンウォーカー

これらは私のお気に入りの答えに反対票を投じていますが。
奇跡173

標準が重要です。Ansi規格がUnique Constraintを使用する場合、Unique Constraintを使用する必要があります。
ライウス

1

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

例えば

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

だからfk_xyz、持っているレコードに対してのみユニークですamount != 0


7
SQL Server(質問のタグ)では、WHERE句を使用してインデックスをフィルター処理できます。CREATE UNIQUE NONCLUSTERED INDEX P4_U ON DBO.P4 ( PID ) WHERE TXT = 'qwert' ;
グリーンストーンウォーカー

-3

UNIQUE制約よりもUNIQUE制約が優先されます。制約が一意でない場合、通常のインデックスまたは非一意のインデックスを使用する必要があります。制約も別の種類のインデックスです。インデックスはアクセスを高速化するために使用されます。

一意のインデックスにはwhere句を含めることができます。たとえば、日付列に基づいて毎年インデックスを作成できます

WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'

前述のwhere句の利点を確認できます。
crokusek 14年

3
「制約も別のタイプのインデックスです。」いいえ、そうではありません。いくつかの制約(PK、UQ、FK)は、インデックスを使用することで適用できる場合が多く、多くの場合は強制されます。ただし、すべてのDBMSで必ずしもデフォルトではありません。
ypercubeᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.