ユニークインデックスについて

このQ&Aのポイント
  • ユニークインデックスの存在自体知らず、困っています。ユニークインデックスで指定された列は値が一意でなければならない。主キーの列にはNULL値は不可だが、ユニークインデックスの列はNULL値も可。主キーは一つのテーブルにつき、一つしか設定できないが、ユニークインデックスは複数設定できる。
  • 主キー設定時、暗黙的にユニークインデックスとNOT NULL制約が作成されている。主キーとは別で、明示的にユニークインデックスを指定する必要性とはなんなのでしょうか?
  • 主キーとは別で明示的に指定した方が良い場合と、その実例を教えて頂けないでしょうか?
回答を見る
  • ベストアンサー

ユニークインデックスについて

仕事の関係で、テーブル定義の際にユニークインデックスをどの列の組み合わせにするのか考える必要があるのですが、今までユニークインデックスの存在自体知らず、困っています。 自分自身でネット等で調べた結果以下のことは理解できました。  1.ユニークインデックスで指定された列は値が一意でなければならない。  2.主キーの列にはNULL値は不可だが、ユニークインデックスの列はNULL値も可。  3.主キーは一つのテーブルにつき、一つしか設定できないが、    ユニークインデックスは複数設定できる。(同じ列は指定できない)  4.主キー設定時、実は暗黙的にユニークインデックスとNOT NULL制約が作成されている。 ここまでは分かったのですが、主キーとは別で、明示的にユニークインデックスを指定する必要性とはなんなのでしょうか? 主キーとは別で明示的に指定した方が良い場合と、その実例をどなたか教えて頂けないでしょうか? よろしくお願いします。

  • Oracle
  • 回答数4
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • entree
  • ベストアンサー率55% (405/735)
回答No.1

既に確認されている4 項目の認識で問題ありません。 > ここまでは分かったのですが、主キーとは別で、明示的にユニークインデックスを > 指定する必要性とはなんなのでしょうか? ユニークインデックスとは制約と思っていただいて構いません。 一意でないデータが入らないことを保証するためのものであり、 索引を付与することではありません。 なので、これは「NOT NULL 制約をなぜ追加しますか?」と いう質問の回答と同じようなことです。 > 主キーとは別で明示的に指定した方が良い場合と、その実例をどなたか > 教えて頂けないでしょうか? 整合性のチェックをアプリ側で実装するのではなく、DB側にあらかじめ用意された 機能を使うことで開発コストやバグを抑えるといった利点があるでしょう。 ただ、暗黙的に索引が追加されてしまうため、更新時のパフォーマンスが悪くなるとか そういった問題も発生しえるわけです。 これは「参照制約をつけるべきか否か」という質問と同じようなことでしょう。 正規化やDOA の観点からはきっちりと制約を付けることは望ましいけど、 パフォーマンスやメンテナンスの容易さ(※)の兼ね合いが大事ということに なるかと思います。 ※制約がビッシリ存在するとデータを手修正するのが大変ですよね?

kametora0331
質問者

お礼

ご回答ありがとうございます。 ユニークインデックスを付けた方がよい場合と、 あえて付けない方がよい場合もあるのですね。

その他の回答 (3)

回答No.4

>主キーとは別で明示的に指定した方が良い場合 インデックスとはDBでデータを検索する際の索引です。 ですのでデータを抽出する条件句(Where句)や結合句で指定されない列に指定しても意味はありません。 またインデックスを指定する列が1,または2のように索引をつけても意味がないような種類のデータしか格納されない場合はインデックスを付加しても意味がありません。 またデータ件数がすくないテーブルに対して索引をつけてもパフォーマンスは向上しません。 またインデックスはインデックス用の領域を持ちます。これはUpdateなど更新が実行されると領域が肥 大化していきます。この領域はOracleなどではテーブルの再作成などを実行しないとクリアされない為、断片化の原因となりパフォーマンス悪化の原因となる事がある為、注意が必要です。 上記を踏まえて索引を付けるのはデータ件数がある程度になるテーブルでかつ、データ抽出の際の条件句や結合句となる列、でかつ、ある程度のデータ種類のある列である必要があります。 また上記条件を満たしていてもインデックスを付加したら必ずパフォーマンスが向上するという訳ではないのでインデックス付加後と前とでSQLの実行計画やコスト、実行速度などを計測して付加を判断するという事も必要になります。 いろいろと面倒ですが不要なインデックスを付ければパフォーマンスの悪化を招くこともありますので気をつけましょう。

kametora0331
質問者

お礼

ご回答ありがとうございます。 Updateのたびにインデックス用の領域が肥大するということを初めて知りました。 勉強になります。

回答No.3

#2さんにちょっと追記します。 >インデックスは検索のパフォーマンスをあげるために作成するものです。 >その項目が一意になるのであれば、ユニークインデックスにすればいいと思います。 DB屋さんに聞いた話ですがユニークインデックスの効果は絶大だそうです。ユニークであれば一発で求まるためです。重複であればインデックスからハッシュ的な別途検索処理が動くためパフォーマンスが低下するそうです。 そのため、「インデックスを付けるなら無理してでもユニークインデックスにしろ。」と言われたことがあります。通番を振るなどして無理してユニークキーにしたことがあります。 ご参考まで。

kametora0331
質問者

お礼

ご回答ありがとうございます。 その時の環境次第な面もあるかもしれませんが、 パフォーマンス的にも、ユニークインデックスが有利な場合が多いのでしょうね。

  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.2

インデックスは検索のパフォーマンスをあげるために作成するものです。 その項目が一意になるのであれば、ユニークインデックスにすればいいと思います。 重複する値を許さないという意味であるならユニーク制約が正しいと思います。 (ユニーク制約を設定した場合、基本的にはユニークインデックスが作成されますが) ですので、ユニーク制約を指定するという意味で考えてみます。 >テーブル定義の際にユニークインデックスをどの列の組み合わせにするのか考える それは、要件で決まることなのではないのでしょうか? 業務上、その(それらの)項目が重複してはいけないならユニーク制約を付けましょうとしか言えない気がします。 たとえば、何かの会員登録などで「主キーはユーザ名だけど同一メールアドレスでの複数登録は許さない」 といった場合は、主キーとは別にメールアドレスにユニーク制約を付ける必要があります。 もしくは、テーブルの主キーにはサロゲートキーを使い、ナチュラルキーにあたる項目にはユニーク制約を付ける場合もあります。 これはモデリングの手法によりますね。 自分はDB設計をしたりする立場ではないので妥当な回答であるか分かりませんが、参考になれば幸いです。

kametora0331
質問者

お礼

ご回答ありがとうございます。 分かりやすい例を示していただきありがとうございます。 主キー以外でも一意にしたい項目がある場合もあるのですね。

関連するQ&A

  • 主キー、インデックスが作成できない

    お世話になります。 SQLserver2000とACCESS(フロント)で使っております。 主キーもインデックスも設定していなかったテーブルに エンタープライズマネージャから主キーを設定しようとしたのですが、保存しようとすると以下のエラーが出てしまいます。 もともと更新クエリを作成したのですが、”更新可能なクエリであることが必要です。”とエラーが出てしまい、いろいろ調べるうちに主キーを設定していないから??と思い、設定しようとしたのですがうまくいきません。。宜しくお願いします。 ■エラー内容 テーブル 'テーブル名 (ユーザー名)' - インデックス 'インデックス名' を作成できません。 ODBC エラー : [Microsoft][ODBC SQL Server Driver][SQL Server]インデックス ID 1 で重複したキーが見つかったので、CREATE UNIQUE INDEX は終了しました。もっとも重要な主キーは 'XXXX-00XXXX-00-A1 ' です。 [Microsoft][ODBC SQL Server Driver][SQL Server]制約を作成できませんでした。以前のエラーを調べてください。 [Microsoft][ODBC SQL Server Driver][SQL Server]ステートメントは終了されました。

  • 主キーとインデックスの違いについて

    はじめまして。 SqlServerのテーブル作成をしていますが、 主キーとインデックスの違いがよく分かりません。 いつも主キーの設定は行っていますが、インデックスの設定も必要なのでしょうか。(パフォーマンスの向上の為?) 基本的な事ですみませんが ご教授お願いします。

  • インデックスについて

    初歩的な質問ですみません。 DBでよく「インデックスを張る」という風な言葉が使われますが、具体的にはどういうような事をすればよろしいのでしょうか。 またそれは、単に、ある列に対してユニークやNOT NULLなどの制約を付与するのとは異なるのでしょうか。 どなたかご教授願います。 また、参考になるようなサイトなどありましたら、教えてください。

  • 主キーにインデックスは貼らないと駄目でしょうか?

    いつもお世話になっております。 テーブルを作成したときに主キーのインデックスは改めて 貼る必要があるのでしょうか? それとも自動的に インデックスを貼ってくれます?

  • データベース22年度 午後I 問2 設問2

    ”会員”テーブルの項目は、NULL不可となることが静的に決まらないので、列ごとにNOT NULL制約を定義できない。そこでNULL不可であることを動的に管理する”項目チェック”テーブルを図のように定義した。・・・ というNULL不可を動的に管理する”項目チェック”テーブルの空欄埋め問題で、解答は以下の通りでした。 項目チェック(一連番号,会員列名称,会員区分,職業区分) 一連番号が主キー しかしながら一連番号がどうして必要なのか分かりません。 たとえ新たな職業区分を追加したとしても{会員列名称,会員区分,職業区分}を主キーにしておけばまかなえると思うのですが。 一連番号がサロゲートキーにしか思えないのですが、どなたか解説お願いいたします。

  • ALTER TABLE文の書き方について

    お世話になります。 今、以下のような列からなるテーブルがあります。 ・A(主キー) ・B(主キー) ・C(主キー) ・D(主キー) ・E(NOT NULL) ・F 列A、B、C、Dが複数列の組み合わせで主キーです。 このテーブルを以下のように変更したい場合、 どのようなALTER TABLE文を書けばできますでしょうか。 ※列A、B、C、Dの主キーはやめて、列A、B、C、D、G、H、Iの  複数列によるUNIQUE制約を設定。 ・A(UNIQUE&NOT NULL)← 主キーはやめる ・B(UNIQUE&NOT NULL)← 主キーはやめる ・C(UNIQUE&NOT NULL)← 主キーはやめる ・D(UNIQUE&NOT NULL)← 主キーはやめる ・E(NOT NULL) ・F ・G(UNIQUE)← 追加 ・H(UNIQUE)← 追加 ・I(UNIQUE)← 追加 やりたいことは、列G、H、Iを追加して、 A、B、C、D、G、H、IでUNIQUEにしたく、かつ、 追加したG、H、IはNULLを許容したいということです。 A、B、C、D、G、H、Iの複数列の組み合わせで主キーも 考えましたが、主キーにするとNULLが許容できないと いうことで、上記のようなレイアウトを考えました。 他に上手い方法があればご教授いただけると幸いです。 ちなみに列のデータ型はすべて可変長の文字列です。

  • インデックスの作り方

    MySQL4.1.19を使っているのですが、ユニークなインデックスの作り方で困っています。 例えば、 create table dttest ( a int NOT NULL , b int NOT NULL , c int NOT NULL , d int NOT NULL , CONSTRAINT PK_dttest PRIMARY KEY ( b ) ) type=InnoDB; というテーブルがあったとして、 aフィールドはユニークのインデックスを作り cフィールドは、重複可能なインデックスを作りには どうすればよいのでしょうか? 初歩的な質問で申し訳ありませんが、 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • インデックスまたは主キーにはnull値を使用できません

    こんにちは。 アクセス初心者です。 練習のため給与管理をAccessで作っています。 単純なクエリを基に入力フォームを作りましたが (1)新規データを入力すると 「インデックスまたは主キーにはnull値を使用できません」 というエラーが出ます。 すべてのフィールドにデータは入っているのですが・・。 確認すべき場所があれば教えてください。 (2)またフォームに、1列目が会社リスト、2列目が会社名というコンボボックスを作りました。 コンボボックスで選択後、フォームで表示されるのは会社名、 テーブルに入力されるのは会社リストという設定はできますか? どうぞ宜しくお願いします。

  • mysqlのインデックスについて質問です。

    mysqlのインデックスについて質問です。 http://archiva.jp/web/server-side/sql_02.html に、 『mysqlでは1つのクエリ実行で、1つのテーブルにつき1つのインデックスしか使用できない』 とあります。 よく以下のようなテーブル定義を見かけますが、 CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; idとuser_idを条件にするクエリであれば、上記制約を満たすため、 KEY `id_user_id_idx` (`id`,`user_id`) の複合クエリを定義すれば良いのでしょうか? また、idとuser_idとfile_idを条件にするクエリも考慮に入れた場合、 テーブル定義は以下のようにするのでしょうか? CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`), KEY `id_user_id_idx` (`id`,`user_id`), KEY `id_user_id_file_id_idx` (`id`,`user_id`,`file_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 最後に、create table 時のインデックスの指定は、 INDEX `user_id` (`user_id`), のようにもできますが、INDEXとKEYの違いは何かあるのでしょうか。

    • ベストアンサー
    • MySQL
  • INDEXヒントとは?

    @ITの以下のページで、 LIKEの中間一致、後方一致で検索する場合は索引が使用されない。対処方法には、「INDEXヒントを使用する(索引列にNOT NULL制約が必要)」 と書かれています。http://www.atmarkit.co.jp/fdb/rensai/orasql07/orasql07_1.html INDEXヒントとは一体何のことでしょうか? 現在チューニングを行っておりますので、有効な方法であれば是非利用したいのです。