kagamihogeの日記

kagamihogeの日記です。

データベースパフォーマンスアップの教科書 基本原理編

最初はOracle Databaseの実行計画の見方良くわからなんな、というのが出発点だった。ぐぐってると@IT:Databaseフォーラム全記事インデックス - Oracle SQLチューニング講座をオススメしてる人がいて、まずこれを読んだ。読んだが、もうちょっと根本的なところでRDBMSに対する理論の理解不足を改めて認識することになった。それで改めてぐぐってると本書を紹介している人がおり、やや難易度が高い本であるらしかったがとりあえず読んでみることにした。結論から言うと今の俺には読んで正解な本だった。部分的には理解できなかった箇所があるものの、全体としては非常に面白く読むことが出来た。

本書で書かれているのは、RDBMSの各種機能や構造は原理的にこれこれこーいう作りになっているので、その原理に沿うと、こういう使い方―何らかのSQL発行とほぼ同義―をするとこういう動作となる、というもの。一見すると不可解な動作であっても、背後に控える原理とそれが適用されたときの結果には繋がりがある、という態度が貫かれている。当然、RDBMSは巨大なシステムで様々な要素が絡み合うので理解するには一筋縄ではないし、現実に使われるテーブル構成やSQLはもっと複雑なものである。よって、筆者が言うように原理を知っただけでどうにかなるものでは無いにしろ、基本原理を知る有り難味は確かにある。

というのも、俺は昔からRDBMSに対して素朴な疑問を幾つか持っていたのだが、それを本書は見事に氷解してくれた。たとえば、なぜRDBMSではインデックスが重要な位置付けにあるのか? というもの。一言で言えば、データがどのように格納されるのかと、データをどのような順序で取得するのか、を分離するところにある。パフォーマンスの面で言えば、テーブルの構造に関係無くインデックスを貼れる点が重要。要は、データが溜まりまくってしまっても後から手を打てる、ということ。

ただし、B-Treeインデックスはインデックス内にも重複してデータを持つ。これはデータアクセスがインデックスだけで済む可能性を生むメリットになる一方、重複データを持つことは明らかにデメリットである。ビットマップインデックスはそうした重複が無い一方、B-Treeインデックスほどの柔軟性は無い。ここからも明らかなように、こうすれば必ず速くなる、という技は無いと言っていい。大抵の技術にはメリットとデメリットがあるので、DBを使う側の人間に必要なのは、ある技術を使うべきか使わないべきかを判断する基礎知識であろう、と本書は述べている。

特殊な道具であればあるほどそれが有効な場面は限られてくる。しかし、特殊な状況であることを認識して、特殊な道具を使えば高い効果を得られることにも触れている。その例の一つとしてクラスタリングテーブルを挙げていて、テーブルのリレーションの柔軟性を捨ててでもテーブルの結合度を高めて検索性能を上げたい場合には有効である、としている。もちろん、より重要なのは頻繁に使う技術の方の基礎知識であるのだけど。

本書は中身のほとんどの箇所でインデックスに触れるのだけど、結合インデックスの謎についても答えてくれた。結合インデックスは、事前に複数の列をたばねておいたインデックスとでも言うもの。これが重要なのは、事前に複数列をたばねておくことで、実際にその複数列を使用する条件が来たときに高速に応答できる、という点にある。ただし、単一列に比べれば柔軟性は落ちることになり、結合インデックスが上手く使えない状態になると途端に効率が悪くなる。ここにもやはりトレードオフが見られる。また、どの列をどの順序で結合すべきかは、分布度が良いかどうかよりも、どのような使われ方をするのかが重要である、というのも驚きであった。

他の疑問としては、RDBMSはどのようにJOINをしているのか? というのもある。クラスタリングのような手段を取らない限り、二つのテーブル間を繋ぐものは何も無い。いくら同一の列名・同一内容のデータが入っているといっても、それは人間が見たから分かることであり、機械が判別できるようはなっていないのでは、というもの。これは俺だけの疑問でなく、速度面からJOINを疑問視する人間は多いようで、本書のJOINの章は、あるテーブルにSELECTを発行してループで回してもう一つのテーブルに主キーなりでSELECTを発行する、という手法の是非から始まる。この手法は当然SELECT文の発行回数からして既に不利なのだが、筆者はそれが有効である局面でなら使っても良い、としている。
JOINにも幾つかの種類があるがネステッドループジョインで言えば、結合にはインデックスを上手く利用している。先行テーブルから受けた条件を、連結先のインデックスを見に行くことで結合を行っている。順序立てられた説明を良く読めば当たり前でごく自然なことなのだが、そのことがかえって俺には印象的であった。

インデックス以外のトピックで言うと、なぜSELECT * FROM CUSTなどシンプルなクエリは即時で結果を返せるのか? にも答えが書いてあったのも興味深かった。CUSTテーブルが何千万行とあろうと、SQL*Plusなどのツールでは1秒とたたずに結果が返り始める。これは部分範囲処理の特性で、RDBMSのテーブルは理論上は順序が無いことに由来する。データには格納順序の概念が無いので、最速で返せるデータから返し初めても良い。キャッシュにあればそれでよいし、ディスク上に最速でアクセスできるブロックから返せばよい。

反対に、ORDER BYなどSORTが走るものは、すべてのデータにアクセスしてからでないと最初の数件を返すことが出来ない。本書では全体範囲処理と呼ばれるもので、クエリのパフォーマンスを考える上では重要な視点になる。部分範囲処理は、たとえ結果が膨大であっても最初の数件を返すことは高速に行えるので、オンライン処理では当然に重要な考え方となる。また、集計とかは全体範囲処理せざるを得ないが、それでもサブクエリやインラインビューで全体範囲処理となる部分をくくって部分範囲処理に誘導するテクニックなどはかなり面白かった。

実行計画の見方に関しては、本書を読み進める上で自然に覚えることになる。この本はあちこちであるクエリがどういう実行計画になるかを解説している。実行計画の各行に現れるアクセスパスがどういう性質のものかを知ることと、実行計画の見方は一体の関係にある。結局のところ原理的な意味から学び始めるのが近道だった。

最後になってしまったが、本書は明示してないもののOracleを前提に書かれている。著者曰く、特定のRDBMSに依らない解説をしているそうだが、それがどの程度真実なのかは、俺はOracle以外大して知らないので何とも言えない。しかし、パフォーマンスを論じる上では特定のRDBMSは前提にしなければ話を進めるのは難しいと思われるが。

そういうわけで、Oracleを勉強しなおしてる最中の俺にとっては大変貴重な一冊となりました。

データベースパフォーマンスアップの教科書 基本原理編

データベースパフォーマンスアップの教科書 基本原理編