2012-04-10 20 views
0

Microsoft SQL Serverでは、テーブルを作成するときに、実際には一意にする必要がないにもかかわらず、列に一意制約を使用することには何らかの欠点がありますか?必ずしも必要ではないにもかかわらず、テーブル内のユニーク制約を使用する必要がありますか?

の例では、ユーザー管理システムにおける役割と言うの説明のようになります。

CREATE TABLE Role 
(
    ID TINYINT PRIMARY KEY NOT NULL IDENTITY(0, 1), 
    Title CHARACTER VARYING(32) NOT NULL UNIQUE, 
    Description CHARACTER VARYING(MAX) NOT NULL UNIQUE 
) 

私の恐怖は、他のテーブルで頻繁に挿入を行うときに、この制約を有効にすると、非常に時間のかかるプロセスになるということです。この制約がどのように検証されるかはわかりませんが、非常に効率的なやり方で、あるいは線形比較として行うことができるようです。

答えて

4

あなたの恐怖は真実になります:UNIQUE制約はインデックスとして実装され、これは時間と空間を消費します。

新しい行を挿入するたびに、データベースはテーブルを更新する必要があり、ユニーク制約ごとに1つのインデックスも更新する必要があります。

だから、あなたによると:

列に一意制約を使用して、あなたは本当に答えはノーである

、使用しない一意であることを必要としないにもかかわらず、それ。時空間の短所があります。

サンプルテーブルには、Idのクラスタードインデックスと、2つの追加インデックス(各ユニーク制約の1つ)が必要です。これはスペースをとり、挿入物上の3つのインデックスを更新する時間を費やします。

これは、これらのフィールドでフィルタリングされたクエリを作成した場合にのみ正当化されます。ちなみに

: オリジナルポストサンプルテーブルには、いくつかの欠点があります:

  • 構文はSQL Serverの構文ではないことを(そして、あなたは、SQL Serverのように、このタグ付き)

  • あなたが作成することはできません。 varchar型(最大)のインデックス列

あなたは構文を修正し、このテーブルを作成する場合:

CREATE TABLE Role 
(
    ID tinyint PRIMARY KEY NOT NULL IDENTITY(0, 1), 
    Title varchar(32) NOT NULL UNIQUE, 
    Description varchar(32) NOT NULL UNIQUE 
) 

sp_help Roleを実行すると、3つのインデックスが見つかります。

+1

私はMicrosoft SQL Server 2008 R2が実際にSQL Serverの構文であると主張します。 –

+1

あなたは正しいですが、元の投稿は無意味です。このテーブルの列を参照するFKがある場合、他のテーブルの挿入はこのテーブルにのみ影響します。その場合、FKはPKまたは固有の制約がこれらの列に存在することを要求します。その答えは、制約チェックを可能にする(そしてスピードアップする)固有の制約を避けることはできません。 – JotaBe

+1

@Michael J. Gray:構文はSQL Server 2008 R2で機能しますが、(最大)列に一意のインデックスを作成することはできません。 – JotaBe

1

データベースでは、UNIQUE制約をバックアップするインデックスが作成されるため、一意性検査を行うには非常に低コストである必要があります。

http://msdn.microsoft.com/en-us/library/ms177420.aspx

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

+0

これを念頭に置いて、私は主観的な質問をもう少し持っていると思います。データが常にユニークであることがわかっている場合は、通常、アプリケーションを正しく機能させるには一意である必要はありませんが、それを制約するのがよい方法ですか? –

+3

いいえ、私はその良い練習とは言いません。 「ユニーク」とは、同じデータを持つ2つの行が有害な影響を及ぼす可能性のある状況を意味します。 – StilesCrisis

-1

SQL Serverでは、データ型tinyintには256の異なる値しか与えられません。あなたがID列の外で何をしていても、非常に大きなテーブルで終わることはありません。インデックス付きの列が12個ある場合でも、確実にすぐに実行されます。

通常、代理キーのほかに少なくとも1つの一意制約が必要です。あなたが持っていない場合、あなたはこのようなデータで終わることになります。

1 First title First description 
2 First title First description 
3 First title First description 
... 
17 Third title Third description 
18 First title First description 

このようなデータは通常間違っています。 テーブルへの外部キー参照を使用するテーブルでは、使用される「First title」の数など正しくレポートすることはできません。

私は、ユーザー管理システムで役割の複数の同じタイトルを許可することは設計上の誤りであると主張します。私はおそらく、 "タイトル"もその列の本当に悪い名前だと主張します。

+0

Downvoted。 。 。どうして? –

+0

0は有効な値なので、TINYINTは実際には256の異なる値を返しますか? –

+0

@ MichaelJ.Gray:良い点。修正されました。 –

0

通常、あなたがデータを知っていれば、それを制約することをお勧めし 常に一意になりますが、アプリケーションが正しく機能するために ことは必ずしも一意である必要はありませんか?

私の質問:2つの役割が異なるタイトルでも同じ説明を持つことは意味がありますか?例えば

INSERT INTO Role (Title , Description) 
    VALUES ('CEO' , 'Senior manager'), 
      ('CTO' , 'Senior manager'); 

私には説明の使用を評価していないようです。重複が多い場合は、次のようなことを行う方が意味があるかもしれません。

INSERT INTO Role (Title) 
    VALUES ('CEO'), 
      ('CTO'); 

INSERT INTO SeniorManagers (Title) 
    VALUES ('CEO'), 
      ('CTO'); 

しかし、再び重複は予想されません。

私はこれが低い活動表であると仮定します。あなたは、他のテーブルで頻繁に挿入するときにこの制約を検証することを恐れると言います。さて、それは起こりません(別のテーブルが更新されたときにこのテーブルを更新することができないトリガーがない限り)。

個人的には、私は設計者(ビジネスアナリストなど)にユニークな制約を適用しないことを正当化するよう依頼します。彼らができなければ、私は常識に基づいてunqiueの制約を課すでしょう。このようなテキスト列の通常のように、私もCHECKの制約を適用します。先頭/末尾/二重スペース、長さゼロの文字列などを許可しないようにします。

+0

私は他のテーブルについて言及したとき、少し曖昧だったと思います。私は 'Role'テーブルと同様の' UNIQUE'制約を持つテーブルを意味しました。挿入と更新の回数が増えました。この例を使って質問を理解するのは簡単だったし、そう思った。 –

関連する問題