例えば、テーブルのいくつかの列(欄)に対して、高速にデータにアクセスするためのインデクス(索引)が定義されているとする。ユーザーの指定したデータ取り出し条件を解析して、インデクス経由でアクセスした方が速いのか、どのインデクス経由の方が速いのか、それとも直にテーブルの行レコード全件を直にアクセスした方が速いのかといったアクセス手順のコストを評価して決める方式や、インデクスをユーザーが定義する際に、そのインデクスが付けられる列の値に重複がない(UNIQUEである)ことや、使用可能なインデクス候補として選択された場合に優先して使用することなどの情報をユーザーに指定してもらい、その情報を最適化処理に適用するといった方式や、それらを併用した方式などがあり、このような工夫によりデータアクセスの高速化を図ってきた。さらに、実際のシステムに適用してみると、インデクスを使ってアクセスするよりもテーブルのレコード全件を素直にアクセスした方がよほど早いケースなどもあったりして、現場で得られたノウハウも規則化して最適化処理にフィードバックして磨きをかけていった。
また、ユーザーから指示されたSQL文をその場で解析・最適化して実行する方式は、アドホックな検索要求に対して即応できるという点で従来の構造型DBにない優位点であったが、定型的な業務システムにおいてはこの解析・最適化処理部分が逆にオーバーヘッドとなり、業務処理プログラム中に書かれたSQL文を事前に解析・最適化しておくプリプロセス方式を採用して、基幹業務システムへの適用を図っていった。
リレーショナルDBのもうひとつの大きな特徴として、テーブルの特定の列を軸として複数のテーブルを結びつけて必要なデータを取り出すという結合演算(join)がある。この結合演算処理の高速化もリレーショナルDBMSの大きな技術課題であり、初期の頃から精力的にさまざまな研究開発がなされてきた。詳しい説明は省略するが、初期の成果として、入れ子ブロック方式、マージ方式、ハッシュを利用した方式などがあった。このように結合演算処理を含めて、リレーショナルDBのデータ操作では集合演算を基本としているため、ソート・マージ処理に多くのCPU時間を取られる傾向が強く、ソート・マージ処理の高速化をハードウェアで支援する試みもなされた。
このような例として、日立製作所では、大量の文献データの高速検索システムを支援するなどのために、メインフレーム上にリレーショナルDB処理の要素機能を付加して、大容量主記憶上でパイプラインにより要素データを並列処理してデータベース処理を高速化するベクトル計算機IDP(Integrated Database Processor)を1988年に製品化している。
次にリレーショナルDBにおけるデータ更新の問題について少し触れてみよう。
本連載の第4回で解説されたように、オンライントランザクションシステムにおいて、1つのトランザクションでのデータベース更新処理は、他のトランザクションでのデータベース処理の影響を受けず、しかも中途半端な状態を残さずに完結させる必要がある。それと同時に、他のトランザクションでのデータベース処理をできるだけ待たせずに並行処理性を高める必要もある。
このための手法として、処理対象のレコードにできるだけ短時間ロックを掛けて他のトランザクションからのアクセスを排除する手法が構造型DBの時代から用いられていた。リレーショナルDBにおいても基本的な考え方は同じであったが、集合演算を素直に処理すると一度にロックされる量が膨大になり、いわゆるロックの粒度をいかに小さくするかという問題に対してさらに工夫が必要となった。
例えば、「社員」テーブルの「A部門」という「所属部門」に属する社員全員の「給料」を5000円上げるという集合演算的な更新処理は、SQLのUPDATE文1個で書くことができる。このデータ更新処理を実行する間、このテーブル全体をロックしておけば話は簡単であるが、もしも別のトランザクションで、「B部門」に所属する全員の「給料」を4000円上げるというUPDATE文の処理を同時に行うとしたら、このトランザクションは最初のトランザクションの処理が完了するまで待たされることになる。
別の方法として、「所属部門」列にインデクスが張られていた場合に、最初のUPDATE文の処理でそのインデクス全体をロックすることも考えられるが、並行処理できない点で同様の話となる。このようなことを避けるために、「A部門」や「B部門」の社員の行レコードだけをロックするとか、「所属部門」インデクスの「A部門」や「B部門」という値だけをロックするなどの工夫を行って、トランザクションの並行処理性を高めた。
これまで、メインフレーム時代に試みたリレーショナルDBMSの高速化という観点で述べてきたが、余談を一つ。筆者はリレーショナルDBMSの初期の製品開発に従事したが、開発当初は、リレーショナルDBは集合演算処理が要であり、100件ヒットするデータ検索というような集合処理がいかに早くできるかという集合演算の最適化というところに目がいっていた。しかしながら、最初に適用された実システムは、1件検索や1件更新がほとんどの定型的な業務処理であった。そこでの多くの経験を通じて、いくら集合演算処理といっても、その基本要素は1件のレコードの読み出しであり更新である、構造型DBMSで磨いてきた1件検索や1件更新を磨くことがリレーショナルDBMSでも非常に重要なことだと骨身に染みて感じた次第である。