【DBウィーク最終日】データベース・インデックスの基礎 | 若手エンジニアのブログ

若手エンジニアのブログ

文系出身の若手女子エンジニアによる技術ブログ。
日々の経験や学びをアウトプットするためにブログを書いています。
バックエンド(Java+SpringFramework)を経てインフラエンジニアになりました。
今は育休中につき、本で勉強したことを中心にアウトプットしています。

「DBウィーク」の最後は、

データベースのインデックス(索引)の基礎について学びたいと思います。

 

1.インデックスとは

2.インデックスの作成

3.B-treeインデックス

 

対応するOracleドキュメントはこちら

また今回は、ミック著 『達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ』も参考にさせていただきました。

 

1.インデックスとは

DBにおけるインデックス(索引)は、テーブルに格納されているデータを高速に取り出すための仕組みの1つ。

本の最後のほうについている索引と、役割は本質的に同じ。
 ・索引があると、本の中の知りたい情報にすぐにアクセスしやすい(探すスピードが格段に上がる)
 ・索引は無くても良い(本の中身自体は変わらない)
 ・1つの本に対して複数種類の索引があっても良い(五十音順の索引と、テーマ別の索引があっても良い)

データベースでも、インデックスがあることで、処理速度の大幅な性能改善が見込める。

もちろん、インデックスは無くてもDBの中身(テーブルに格納された値)が変わるわけではない。
また、状況によって、より適切なインデックスを使い分けることができるよう、複数のインデックスがあってもOKである。

 

ただしこうした性質のため、インデックスは、実際のテーブルデータの格納先とは、

物理的にも論理的にも独立した場所に格納する必要がある。

 

2.インデックスの作成

◎手動作成

インデックスを作成するには、前提として以下の条件を満たしている必要がある。

 

 ■DBユーザ自身のスキーマ内にインデックスを作成する場合(以下の少なくとも1つを満たしている必要)
  ・インデックスを付ける表またはクラスタが、自分のスキーマに格納されている。
  ・インデックスを付ける表に対するINDEX権限を持っている。
  ・CREATE ANY INDEXシステム権限を持っている。

 

 ■DBユーザ以外のスキーマにインデックスを作成する場合(以下の両方を満たしている必要)

  ・CREATE ANY INDEXシステム権限を持っている。
  ・目的のスキーマの所有者が、索引または索引パーティションを作成する表領域への割当て制限を持っているか、UNLIMITED TABLESPACEシステム権限を持っている。

 

※システム権限など権限に関する内容は以前の記事で扱っています。

 

 

インデックスを作る基本構文は以下の通り。

      CREATE INDEX (インデックス名) ON (テーブル名)

 

別ユーザのスキーマに作るとか、後述するようにインデックスには複数の種類があるため、作成する種類を指定したいとか、

ニーズに合わせた設定もオプション引数で可能。

詳細はOracleのドキュメントで説明されている。

 

ただし、インデックス作成にあたっては、例えば以下のような考慮事項がある。
 ・データ量が少ないと、インデックスを利用するよりもテーブルのフルスキャンでレコード検索したほうが早いことがある

 ・インデックスを利用して、見るべきデータを絞り込めるはずが、絞り込んだデータが多すぎてあまり効果が出ない

 ・最適な箇所にインデックスを定義できていない/不要な箇所にインデックスを定義してしまっている

 

データベースのデータは刻々と変化していくもののため、データ量を勘案したインデックスの作成有無や、

最初は不要だったが徐々に必要となってくるインデックスがあるかもしれない等、

慎重に想定して設計しないと、パフォーマンス向上効果が低減してしまう(どころか、かえって処理が遅くなってしまうこともありうる)。
 

◎自動作成

インデックスを作ったり、どのインデックスを使うかを手動で指定したりすることもできるが、

設計は前述の通り難しい。

そのためOracle Databaseでは、インデックスの管理(インデックスの作成・削除と、利用するインデックスの選択)を最適化するために、
自動でインデックスを作成する機能(自動索引)が存在している。

 

自動索引では、バックグラウンドで15分毎に以下のプロセスを実行してくれる。

 

No プロセス概要 説明 ブログに例えると
1 自動索引候補の識別 テーブルの統計情報が利用できるかを確認する。これにより、自動索引の作成対象を洗い出す。
(リアルタイム統計でない、失効した統計となっている→自動索引作成の対象とならない)
ブログネタを考えるイメージ。
「これはブログにしたら面白そう」/「これはブログにしない」といった選別をし、書く対象を絞り込むのに近い。
2 自動索引候補に対する
不可視の自動索引の作成 
No1の確認で、自動索引の作成対象と判断されたテーブルに対し、自動索引を作成する。

ただし作成段階では、まだ実際に使えるインデックスとはなっていない。
このように、まだ使用できない自動索引を、「不可視の自動索引」という。
ブログの下書きを作成する。

ブログの実態はあるが、まだ他の人からは読めない状態である。
3 SQL文に対する
不可視の自動索引の検証
No2で作成された不可視の自動索引について、
「使用するとパフォーマンスが向上する」と判断されれば、可視索引(実際にインデックスとして使える状態)となる。

パフォーマンスが向上しない場合、
使用禁止索引となり、
最終的に④で削除されることになる。
【可視索引】
下書きとしていたブログを公開することで、他の人が読める状態にするイメージ。

【使用禁止索引】
下書きで書いたけどいまいちなのでお蔵入り→その後、下書きを整理して削除するようなイメージ。
4 未使用の自動索引の削除 長期間(デフォルトで373日)使用されていない自動索引を削除する。 (アメブロに同様の機能がないのでメールで例えると…)

ゴミ箱に入れられた過去のメールが、
一定期間経過後に、自動的に完全削除されるイメージ。

 

このようにして、15分毎に最新化されていくため、動的索引のほうが状況に応じたインデックスの精度が高くなると言える。

 

 

3.B-treeインデックス

◎インデックスの種類

インデックスには、複数の種類がある。

B-treeインデックス、ビットマップインデックス、ファンクションインデックスなどなど…。

 

その中でも、データベース全般において代表的なインデックスであり、

Oracle Databaseでもデフォルト利用されているB-treeインデックスの構造を見てみたい。

(自動索引で作られるインデックスは、すべてB-treeとなる)

 

◎B-treeインデックスとは

以下のようなバランスツリー(平衡木)の木構造で、データを保持するインデックスのこと。

※バランスツリー(平衡木)とは、ルート(最上位)から最下層までの距離が一定になっている木構造のことである。

また、左側が小さい数、右側が大きい数という、ソートされた状態で構成されている。

 


B-treeでは、最下層部分(リーフ/葉 と呼ばれる)が、実データにアクセスする情報を持っている。

そのためB-treeを利用するときは、

上から順に実データに近い値をたどることで、リーフにたどりつき、そこから実データにアクセスすることになる。
 

◎B-treeインデックスの優れている点

B-treeインデックスの優れている点として、以下3点があげられる。


・どんなキーでも、ほぼ同じ速度で実データまでたどり着ける。

  バランスツリーの構造をとる(=距離が同じ)ため、速度も変わらない。

 

・インデックス生成だけでなく、更新や削除コストも比較的かからない。

  インデックスはデータベースの状況に応じて更新していくものだが、

  その更新にかかるコスト(リソースや時間)が、他の種類のインデックスよりも比較的少ない。

  しかもDBデータが増えたとしても、コスト増加の度合いが緩やかである。

 

・ソート処理に強い。

  ソート(データの昇順/降順並び替え)は、データベースにとってコストの大きい処理となる。

  だが実務では、ORDER BY句(ソートを指示するSQL)はもちろん、

  内部的にソートが行われるSQL句が複数使われることも多い。

  B-treeでは、そもそもキーとなる値をソートした状態で保持しているため、改めてソートする必要がなく、コスト削減につなげることができる。

 

 

他のインデックスについてはぼちぼち勉強していこう…(´・ω・`)

 

 

 

余談。(雑記)

今日はGW最終日ですね。

 

私は今年2月に結婚したんですが、

そこからずっとバタバタしていて(引っ越しとか結婚式とか普段の家事タスク・夫の休日出勤とか…)、

結婚してから約3か月後に初めて、夫とゆっくり過ごせました。

 

コロナ禍なのでずっと家にいましたが、大切な人と時間を共有して、

何気ない日常を笑顔で送ることができるって、とても幸せで、素晴らしいことやなあと改めて思いました( *´`)

 

これからも家庭と、エンジニアの仕事を、両方大切にしていきたい。

そう思える、とても充実したGWでした(#^^#)

 

では!