インデックスの仕組みを図解で説明 〜B木で検索が速くなる理由と、遅くなる場合〜

データベースにインデックスを作ると、なぜ検索が速くなるのか説明できますか?

「検索が遅いならインデックスを張ればいい」と聞いたことがある人も多いと思います。

ですが、インデックスはどんな時でも速くなる魔法ではありません。

インデックスの仕組みと、速くなる場合・遅くなる場合について、図を使って説明していきます。

インデックスなしの全件検索と、インデックスありの検索の比較図。索引で行の場所が分かれば、目的の行へすぐ行ける

インデックスとは?

インデックスは、データを速く探すために、データベースが別に持っている目次のようなもの です。

本の巻末にある索引をイメージしてください。

索引がない本で「DNS」という言葉を探すには、1ページ目から順番に読んでいくしかありません。

索引があれば、「DNS → 52ページ」と調べて、すぐにそのページを開けます。

データベースも同じです。

インデックスがない列で検索すると、表の1行目から最後の行まで、全部の行を調べます。

これを 全件検索(フルスキャン) といいます。

インデックスがあれば、目的の行がどこにあるかをすぐに見つけられます。

B木の仕組み

多くのデータベースでは、インデックスに B木(ビーき) という形を使います。

B木は、データを木の枝のように階層にして並べたものです。

B木で5025を探す図。根で5000以上の枝へ進み、枝で5000〜5100の葉へ進み、葉で目的の値を見つける

一番上を「根」、途中を「枝」、一番下を「葉」といいます。

例えば、社員番号が「5025」の行を探す場合は、次のようにたどります。

① 根で「5025は、5000〜7499の枝へ」と確認する

② 枝で「5025は、5000〜5100の葉へ」と確認する

③ 葉で「5025」を見つけ、その行の場所を知る

1つの枝から、たくさんの枝に分かれているのがB木の特徴です。

そのため、データが何百万行あっても、根から葉まで数段たどるだけで目的の行に着けます。

ちなみに、B木の「B」は二分木(Binary tree)の「B」ではありません。

二分木は1つの枝から2つにしか分かれませんが、B木はもっと多くに分かれます。

B+木と範囲の検索

実際のデータベースでよく使われているのは、B木を改良した B+木(ビープラスぎ) です。

B+木では、葉にすべての値が順番に並び、隣の葉とつながっています。

B+木の範囲の検索の図。最初の1件を木でたどったあと、つながった葉を横に順番に読む

そのため、「社員番号が5001〜5200の社員」のような範囲の検索も得意です。

最初の1件を木でたどって見つけたら、あとは葉を横に順番に読んでいくだけで済みます。

インデックスで遅くなる場合

インデックスは検索を速くしますが、良いことばかりではありません。

データを追加・更新・削除するたびに、インデックスも書き換える必要がある からです。

社員を1人追加すると、表への書き込みに加えて、インデックスもそれぞれ書き換える図

本でいえば、本文に1ページ追加するたびに、索引も直さなければならないのと同じです。

インデックスをたくさん作るほど、書き換える量が増えて、データの登録や更新が遅くなります。

また、インデックスのデータを保存するための容量も必要です。

インデックスが向いている列・向いていない列

インデックスは、どの列に作っても効果があるわけではありません。

インデックスが向いている列と向いていない列の表。値の種類、検索の回数、表の大きさ、更新の回数で比べている

値の種類が少ない列は、インデックスで絞り込んでも多くの行が残るので、効果が小さくなります。

行数が少ない表は、全件検索でもすぐに終わるので、インデックスがなくても困りません。

まとめ

今回はインデックスの仕組みについて説明しました。

インデックスは、データを速く探すための目次のようなもので、多くのデータベースではB木やB+木の形で持っています。

検索は速くなりますが、データの追加・更新・削除の時にはインデックスも書き換えるので、作りすぎると遅くなります。

「検索の条件によく使い、値の種類が多い列に作る」と覚えておきましょう。

データベースの基本については、データベースの種類を図解で解説の記事で説明しています。

表の設計の考え方については、正規化を図解で説明の記事で説明しています。

表をつなげて取り出すJOINについては、SQLのJOINの仕組みを図解で説明の記事で説明しています。