• 締切済み

コンポジット一意インデックスとは?

趣味でPHPとMYSQLをいじってる大学生です。 先日はこちらで助けて頂いてとても助かりました。 ご返答いただきました皆様ありがとうございました。 単発の質問で申し訳ないのですが インデックスの指定をする際に疑問点がでてきたので 質問させて下さい。 タイトルにもあげたのですが、 コンポジット一意インデックスというのは インデックス(インデックスの名前はkeyの値) で複数カラムにインデックス指定するということだと思いますが 一意はユニークというのは 任意の挿入されるレコードは、2つの場合に限定すると 2のカラムを見ると他のレコードとかぶらないというか 要するに2つのフィールドをあわせて考えて、 ユニークであるという理解でよいでしょうか? 言葉がおもいつきませんが 例えば宝くじの  組  番号 購入者 ...etc  A組 0001 B組 0001 A組 0023 C組 ・・・ のようなデータを扱う際に 組と番号にコンポジット一意インデックスを割り振るといいというという理解でいいでしょうか? その理解が正しいか間違っているか? 教えていただけると幸いです。 そして、この理解で正しいのならば もしも 番号=0002 など、2つのフィールドのうち1つで検索した場合だとインデックスは役割を果たすのでしょうか? コンポじゃないと機能しないのか?ということです。 コンポじゃないと機能しないのであれば3つのインデックス つまり、(組,番号[コンポ]),(組),(番号) を作成するのが正しいのでしょうか? よろしくお願い致します。

  • MySQL
  • 回答数2
  • ありがとう数2

みんなの回答

回答No.2

検索条件の指定順は、主要なRDBMSでは意識する必要はありません。 >select ~ from 表名 where 番号='0002' and 組='A' >というwhere句の順序を変えたケースもインデックスが >有効利用できないという理解でよいでしょうか? といった検索条件を指定した場合、(組、番号)で構成されるインデクスがあれば、利用してくれます。 SQLの記述から、アクセス計画(パス)を作成するRDBMSの機構は、「オプティマイザ」と呼ばれます。オプティマイザがアクセス計画を作る方法は、大きく分けてルール(構文)ベースとコストベースの二種類があります。 ルールベースは、条件式の種類で、有効利用できるインデクスを選択します。 例えば、「c1=値1 and c2=値2 and c3 between 値3 and 値4」という検索条件を指定したとします。 c1、c2、c3にそれぞれ単一列で構成されるインデクスがあった場合、RDBMSは、between条件より、=条件の方が、「より絞込みができる」と判断します。 c1とc2に関しては、uniqueなインデクスか非uniqueかで優先順位が違ってきますが、両方がunique、あるいは両方が非uniqueであった場合、「先に条件式を指定した方」、「インデクス定義が古い方」、「両方」といったインデクスが選択され、これは各RDBMSのオプティマイザの内部仕様によって違ってきます。 また、複数列インデクスがある場合は、先頭列からより多くの列をインデクスで活用できる方を優先するといった制御をします。 一方、コストベースは、事前に各キー列の重複度合い、値の種類を取得しておき、その情報を元にアクセス計画を作ります。 例えば、先に挙げた「c1=値1 and c2=値2 and c3 between 値3 and 値4」という検索条件で、c1とc2は重複禁止でなかった場合、c3は範囲条件ですが重複が少なく絞込み効果が高いということもあり得ます。コストベースでは、こういったケースで、c3のインデクスを優先して使ってくれます。 その一方で、コスト情報の収集に時間が掛かったり、追加・更新・削除が多く、コスト情報取得時点と、実際に検索する時点でデータベースの状態が違えば違うほど、最適なアクセス計画は生成されなくなるという留意事項もあります。

widoww
質問者

お礼

ありがとうございます。 RDBMSのつっこんだお話をしていただきありがとうございます。 オプティマイザというのが 最適なアクセス計画を作成してくれていたんですね・・・ おかげさまでRDBMSの検索についても勉強できました。 WHERE句の順序については、オプティマイザという仕組みで最適な(と思われる)インデックスが選ばれるということで安心しました。 データベースの専門の技術者もいるくらいですし、詳細なところまで勉強していくときわめて奥が深そうだということがよく分かりました。 改めてRDBMSのすごさも実感しました。 大変勉強になりました。 ありがとうございました^^

回答No.1

>組と番号にコンポジット一意インデックスを割り振るといいというという理解でいいでしょうか? yes >もしも 番号=0002 など、2つのフィールドのうち1つで検索した場合だとインデックスは役割を果たすのでしょうか? インデクスを構成する先頭列に対し、インデクスを有効利用できる操作を行っている必要があります。なお、インデクスは、検索条件による絞込みだけでなく、order by、group by、distinct、集合(集計)関数などでも活用されます。 <有効利用できるケース例> (1)先頭列でインデクスを利用可能な検索条件 select ~ from 表名 where 組='A' (2)先頭列を含むインデクスを利用できる条件 select ~ from 表名 where 組='A' and 番号 between '0001' and '0010' (3)先頭列からインデクス構成列と同じ順にソート select ~ from 表名 order by 組 select ~ from 表名 order by 組,番号 (3)先頭列で条件検索した上で、2番目の構成列の集合(集計)関数 select max(番号) from 表名 where 組='A' (4)先頭列でのグループ化 select 組,max(番号) from 表名 group by 組 <有効利用できないケース例> (1)先頭列でインデクス有効利用の条件なし select ~ from 表名 where 番号='0001' (2)ソート指定がインデクス構成順と合っていない select ~ from 表名 order by 番号,組 >コンポじゃないと機能しないのであれば3つのインデックス >つまり、(組,番号[コンポ]),(組),(番号) >を作成するのが正しいのでしょうか? 「組を条件に指定せず、番号だけを条件指定することがあるか?」によって違ってきます。 (組,番号)のインデクスがあれば、組だけでのインデクス有効利用、組+番号でのインデクス有効利用が可能です。 もし、「番号」だけの検索もありえるなら、(番号)だけのインデクスを定義する必要が出て来ます。

widoww
質問者

お礼

前回に引き続き、分かりやすいご返答を頂き感謝しております。 つまり、コンポジットインデックスはカラムの順序も含めてインデックス化されるということと理解しました。 select ~ from 表名 order by 組,番号 select ~ from 表名 where 組='A' and 番号='0002' はコンポジットが有効利用できるケースであり select ~ from 表名 order by 番号,組 は有効利用できないと教えていただいたのですが ということは select ~ from 表名 where 番号='0002' and 組='A' というwhere句の順序を変えたケースもインデックスが 有効利用できないという理解でよいでしょうか? それともこのケースはORDER句とすこし並び替えの順序がはいっていないのでSQL側でちゃんと解釈(理解)してくれるのでしょうか? そこだけ気になりました。 組、番号の順で作成すれば組のインデックスは別途作成しなくても コンポジットが有効利用できるということ・・・ 番号だけで検索する要求があるなら、番号のインデックスを作成したほうがいいということで理解できました。 ありがとうございます^^

関連するQ&A

  • MySQLのインデックスの使い方を教えてください。

    MySQLのインデックスの使い方を教えてください。 どうやら、検索性を上昇させるためのもののようですが… phpMyAdminで「構造」タブを開くと、【ユニーク】【インデックス】【全文】というアイコンがありますよね。 【ユニーク】を押すと 種別    :BTREE ユニーク  :はい 圧縮    :いいえ フィールド :(チェックを入れた各フィールドの名前) 一意な値の数:(チェックを入れたうち、なぜか最後のフィールドだけはレコード数が表示されるけど、他のフィールドは0になる。どれかひとつをキー的に扱えば充分ということでしょうか。どれでも大して変わらない?) 照合順序  :A 【インデックス】を押すと 種別    :BTREE ユニーク  :いいえ 圧縮    :いいえ フィールド :(チェックを入れた各フィールドの名前) 一意な値の数:0 照合順序  :A 【全文】を押すと 種別    :FULLTEXT ユニーク  :いいえ 圧縮    :いいえ フィールド :(チェックを入れた各フィールドの名前) 一意な値の数:0 となるようですが… (インデックス名は、チェックを入れたフィールドのうち先頭にあるものの名が勝手に採用されますが、後から変更できるみたいですね) 「複数のフィールドにいっぺんにチェックを入れてからアイコンを押す」のと、「ひとつのフィールドずつアイコンを押す」ので結果が違って、なんだか気持ち悪いです。 バラバラのインデックスを作るのと、ひとつのインデックスにまとめるのでは、どう違うのでしょう? 普通はどうするものでしょうか? 例えば no ryaku  cctld  ei   seisiki 1 日本   .jp  japan  日本国 2 アメリカ .us  U.S.A  アメリカ合衆国    3 中国   .cn  China  中華民主主義人民共和国 のように、すべて(あるいはほとんど)のフィールドが一意である場合の例が知りたいです。

    • ベストアンサー
    • MySQL
  • インデックスを張るべき項目について

    20万件レコードのあるテーブルに、インデックスを張ると INSERTが遅くなるので、WHERE句で検索する項目のどれに インデックスを張るか悩んでいます。 インデックスはパターンが多い程、張った場合に 検索速度が向上すると理解しているのですが正しいでしょうか? であれば、下記1.だけは貼ろうと思っているのですが・・ 1.カラムに入るデータが殆どバラバラのVARCHAR(30) 2.カラムに入るデータは10万パターンのINT型 3.カラムに入るデータは1万パターンのINT型 4.カラムに入るデータはdatetime型 インデックスを張る事でINSERT速度が何%ぐらい下がるでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • ユニークインデックスについて

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

  • インデックスがすぐに壊れます…

    テーブル内の1フィールドにインデックスを設定していますが、内容が頻繁に更新されるせいか1日前後でインデックスが破損し、テーブルへのアクセスができなくなって困っています。 以下、詳細な状況です。 ------------------------------------------ (1)該当テーブルのレコード数は、約16,000,000件 (2)インデックスは[レコード更新日時]フィールドに設定しています。 (3)15分おきにデータの自動更新を行い、数百~数千件のレコードが更新されます。 その際、当然ながら[レコード更新日時]フィールドも更新されます。 (4)1日~2日に1度の割合で(3)の自動更新処理が異常終了します。 SQLのエラーコードはまちまちですが、重要度は決まって20前後の深刻なレベルです。 (5)(2)のインデックスを削除→再作成すると、(3)の自動更新処理は正常に行える (6)以下、(3)~(5)の繰り返し ------------------------------------------ 16,000,000件のうちの数千件といえば、0.1%にも満たない量です。そのために頻繁にインデックスの更新をしているうちにファイルがおかしくなるのでしょうか? (ひょっとしたら、インデックスの更新が完了しないうちに次の自動更新処理が実行されているのかもしれません) 同様のケースをご存知の方、いらっしゃいましたらどのように解決したかを教えてください。

  • インデックスの張り方について

    とあるテーブルのレコード数は、全部で28レコードあります。 このテーブルにはインデックスを張っておらず、シーケンシャルスキャンでDBよりSELECTしています。 通常にシステムを運用する上では問題ないのですが、負荷試験などで同時接続数を50などにしループでDBにアクセスさせるとき、その他の4000万レコード程度あるテーブルをSELECTしてくるのは0.00xxx秒で行えるのに対し、この28レコードしかないテーブルからSELECTしてくる際は、遅い場合で0.xx秒もかかってしまいます。 この28レコードしかないテーブルにインデックスを張っても、レコード数が少なすぎてまったく意味がありませんでした。 ちなみにこのレコードへは下記のようなSELECT文を発行しています SELECT xxx,xxx,xxx FROM xxxx where カラム1 = aaaa AND カラム2 IN (bbb,ccc) AND カラム3 = ddd; このレコードのSELECT文を高速化させるには、どのような手段があるでしょうか。 お手数ですがご教示いただけますと幸いでございます。 DBはPostgreSQL、PHPのWebアプリケーションよりDBにアクセスしています。

  • mysqlのインデックス

    最近インデックスについて学びはじめ、まだ理解が浅いのでお伺いしたいです。 携帯会員制サイトを例に質問させてください。 ユーザーは会員登録時に固体識別番号を登録し、この情報はUIDというフィールドに記録され、既に100万レコード存在したとします。 ドコモの固体識別番号は35から始まり AUは05もしくは07からはじまり ソフトバンクはSNから始まります。 全てのユーザーの最初の2文字の固体識別番号は4通りのいずれかとなってしまいます。 固体識別番号を登録する時点で、暗号化し、最初の一文字目をa-zA-Z0-9の62種類にした方が、簡単ログイン時の処理速度は速くなるといえるでしょうか? ご教示頂けると幸いです。 宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • INDEXについて

    ご教授出来る方、お願いいたいます。 現状(状況) =INDEX(TimeCard演算結果!$1:$65536,38,10*ROW(A1)+COLUMN(A1)-1) 上記計算式を「関数の引数」で見ると、 配列:TimeCard演算結果!$1:$65536={} 行番号:38           =38 列番号:10*ROW(A1)+COLUMN(A1)-1 =10 上記計算式をDate2(シート名)のF3にリンクを張っております。 F3~F92まで下にドラックすると、列番号が10、20、30・・・900と 変化します。 やりたい事 この数式を使い、G3~G92まで下にドラックをした時に 列番号を最初だけ12、あとは22、32、42、・・・・と10間隔で 計算式を入れたいのですが、どう入力すれば宜しいでしょうか? 下にドラックした時に列番号が10間隔に増えている状態にしたいです。どのように列番号に数式を入力すれば、宜しいでしょうか? よろしくお願いいたします。

  • MySQLのインデックスについて

    MySQLのデータベースの設計についての質問です。 AとBの2つのカラムがそれぞれ一致する項目を選びたいのですが、この際AとBの文字列をハッシュにするなどし、これを新たにカラムにしインデックスにしたほうが高速でしょうか? ちなみに、常に、決まったAとBをセットにし選ぶつもりです。 よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • 検索条件が複数の場合のインデックスの張り方

    Mysql5.0 + ASP.NETで開発中です。 サーバーはWindows2003サーバーです。 とある検索サイトを作っていますが、1テーブルのフィールド数が80くらいあります。 また、レコード数は常時100万件程度です。 このテーブルの検索を行うときに、ユーザーが任意の検索条件を設定できるような画面なのですが、実際に検索に使用されるフィールド数は最大で10です。 例えば、where a = 999 and b = 999 や where a = 999 and c = 999 and f = 999 や where b = 999 and d = 999 and f = 999 and g = 999 など、where句で使用されるフィールドがユーザーの指定により常に異なります。(999は任意の値です) ORDER BYに使用されるフィールド数は3です。 現状ではインデックスは張っていないため、かなり検索速度が遅いため、インデックスを張りたいのですが、どのような張り方がいいのかがわかりません。 このような場合、インデックスを張る方法として、どの方法が一番よいのでしょうか? 1.検索に使用される10つのフィールドに1つずつ張ればよい 2.検索に使用される10つのフィールドとソートに使用される3つのフィールドに1つずつ張ればよい 3.where句の組み合わせを全て考えて複合インデックスを張る必要がある。 4.その他 また、80フィールドのテーブルを適当に4つくらいに分けて、検索時に結合すれば早くなったりするものでしょうか?

  • INDEX RANGE SCAN とは?

    OracleのINDEX RANGE SCANについての質問です。 私の理解のレベルでは、INDEX RANGE SCANは範囲検索をする時に発生し、 それ自体は効率的にインデックスを利用している状態である、と理解しています。 もっといえば、betweenを使用したり演算子に「>=」などの不等号を使用した とき以外には発生しないはずと思っていました。 しかし先日、条件部分に「=」等号しかないSQLにてINDEX RANGE SCANが発生しました。 INDEX SKIP SCAN ならまだ話はわかるのですが、間違いなくINDEX RANGE SCANでした。 範囲検索で無い場合にINDEX RANGE SCANになる意味がよくわかりません。 ■以下質問です。 範囲検索の場合にINDEX RANGE SCANになるという私の認識はあっているか。 どのような場合に、等価条件だけの場合にINDEX RANGE SCANになるのか。 等価条件だけなのにINDEX RANGE SCANになる場合、検索の仕組みについて。 ■参考情報として記述しておきます。 バージョンは9iです。 1つのテーブルに対するSELECT文で where句には4つのカラムが等価条件で指定されています。 これらのカラムは条件・カラムの値ともにNULLではありません。 関係あるかわかりませんが、カーディナリティが高いにもかかわらず 適切なインデックスが無いSQLでした。 よろしくお願いします。