データベースと秋の空・RDBMS掌握術!

第3回RDBMSマジック、インデックス(1)

第3回は、データベースを扱う上で最も重要なインデックスについてお話ししたいと思います。インデックススキャンは、必要な情報を全件検索するまでもなく、高速に取り出します。まさに、大量のデータを扱わなければいけないRDBMSには欠かせないもので、チューニングにおいても「インデックスを張る(作成する⁠⁠」というのは基本中の基本です。しかしながら、よく実践されるということは悪い面もあり、不用意に、でたらめなインデックスが使われていることも頻繁に目にします。

もちろん、コンピュータの世界は魔法ではありませんから、マジックのごとくすばやくデータを検索してのけるためには、種も仕掛けもありありで、インデックスには良い面も悪い面もあります。ここではその種の仕掛けを説明して、その功罪両面に迫ってみたいと思います。理解して正しくインデックスを使って頂ければと思います。

インデックススキャンとは

辞書の中からある単語が書かれている文章を抜き出すことを考えてみてください。もっとも単純かつ無駄が多い方法としては、最初から1ページずつめくっていって、該当の単語のある文章を抜き出しつつ最後まで読む、ということでしょう。これはつまるところ、前回説明したシーケンシャルスキャンと同じです。当然ながら、これは大変な時間がかかりますので、こんなことはいちいちやってられません。

ところで、インデックスは日本語では「索引」と訳されます。皆さんは当然のごとく「索引」は書籍にて目にしているでしょう。たとえば

  • 辞書の横に、A, B, C, ……と書いてあって、単語の先頭の文字順に正しい単語を見つけられる
  • 本の末尾にそのものずばりの「索引」ページがあって、そこに単語と、記載されているページの対応表がある

といったものがあります。ご存じの通り、これらをうまく使うことで、全部のページに目を通すよりずっと早く必要な文章を抜き出すことが出来ます。

このパラダイムをRDBMSに持ち込んだものがインデックスとインデックススキャンで、索引を使った検索を一般化したものと呼べるでしょう。まず最初に、事前にデータベースのテーブルの中身を高速に検索出来るような仕組みを用意し、これをインデックスと呼びます。

次に、実際にテーブルからデータを取り出す場合には、まずテーブルではなく作られたインデックスから情報を読み込み、その情報を元にデータを読み込みます。これはシーケンシャルスキャンに対してインデックススキャンと呼びます。これにより全体を読み込むことなく、必要なデータだけを読み込むことができます。

読み込む件数がたとえば100万件のうち1件であれば、インデックスを使うことでデータのほんの一部だけしか読み込まずに済むため、非常に高速に検索が出来る利点があります。というより、インデックスなくして大量データ検索はあり得ないと言ってもいいでしょう。

図1 インデックスとシーケンシャルスキャンの違い
図1 インデックスとシーケンシャルスキャンの違い

いつインデックスを使おうとするか

インデックスは、基本的に特定のカラムに対して付け、そのカラムに関する検索を高速化します。たとえばAカラムにインデックスを張ったとして、Bカラムだけの検索にAカラムのインデックスが使われるようなことはありません。

カラムに対するインデックスの付け方はおおむね柔軟で、複数のカラムに渡って指定する「複合インデックス」もあります。複合インデックスとしてA, B両カラムにインデックスを張った場合、A, Bカラムの両方に検索条件を指定した場合のみ利用できるのが普通です。SQLで例示しますと、必ずインデックスを使う前提なら

select * from tbl where a=1;

というSQLならaカラムに付けたインデックスが、

select * from tbl where b=1;

というSQLならbカラムに付けたインデックスが使われます。

select * from tbl where a=1 and b=1;

というSQLのみ、a, bカラムに付けたインデックスが使われます。あるいはaカラム、bカラムに付けたインデックスも使えます。

また、その内部で使っているアルゴリズムによって、どのような検索を高速化できるかが異なります。ある種類のインデックスは一致検索に、あるものは大小比較に、あるものは全文検索にと、適用分野によって違いがあります。

インデックスは大量検索に向かない

繰り返しになりますが、まず何よりインデックスによる検索は、一部のデータだけ、たとえば100万件から1件だけを読み込むというようなケースでは無類の強さを発揮します。しかし、そのためには、最初にインデックスを読み、その後でテーブルを直接読む、という2段階の行動をしなければなりません。たとえば100万件から100万件のデータを読むと、100万件のデータ自体も読み込んだ上に、さらにインデックスも読み込んでいることになります。これでは当然インデックスなど使わないほうがよいのです。これは図のような特性になります。

図2 シーケンシャルスキャンとインデックススキャンの特性
図2 シーケンシャルスキャンとインデックススキャンの特性

インデックスと更新

インデックスを使うためには、事前にインデックスを整備しなければいけません。これはもちろん作成時に整備されますが、それ以外に、通常データの投入、更新、削除時といった書き込み時に、それに追随した変更がインデックスに適用されなければなりません。

図3 インデックスと更新
図3 インデックスと更新

したがって、インデックスを張ってあるテーブルへの書き込みは、そのテーブルのデータ更新と共にインデックスの書き換えも発生することになり、その分時間がかかることになります。一言で言うと、インデックスを利用すると更新が遅くなります。

どのくらい遅くなるかという目安はあまりありません。しかしながら、一般に大量のデータ投入を行う場合には、インデックスを削除してからデータを投入したほうが早いというのが一般的です。

インデックスは利用を検討するときに「更新が遅くなるのと検索が早くなるのとどっちがメリットか?」ということを吟味してから利用しましょう。検索を大幅に高速化してくれるならよいですが、使うか使わないか分からないようなインデックスなら付けないほうがましなのです。

まとめ

インデックスは

  • 大量のデータから条件にあった一部のデータを取り出すのに有効です。
  • テーブルのカラムに関連づけて利用します。条件も見極めましょう。
  • 検索が速くなる一方で、更新は遅くなります。

という特徴を持っています。

では次回では具体的にどのようなインデックスの種類があるかを説明していきます。

おすすめ記事

記事・ニュース一覧