本ブログエントリーはPernixData社のテクノロジーエバンジェリストであるFrank Denneman氏のブログの翻訳版です。
本記事の原文はDatabase workload characteristics and their impact on storage architecture design – part 3 – Ancillary structures for tuning databasesで閲覧可能です。
ネットワールドのPernixDataに関する情報はこちら。本ブログのPernixDataの記事のまとめはこちら。
データベースのワークロード特性シリーズのパート3へようこそ! データベースは仮想インフラストラクチャの中でもっともI/Oを消費するもののうちの一つだと考えられています。データベース操作とデータベース設計はそれ自身が研究ともなり得るものです。しかし、データベース設計の世界の表面から少し潜ってみるということはとても面白いことだと思いました。PernixDataの製品ディレクタであり、データベースの専門家である同僚のBara Narasimhan氏のもとへ赴き、データベース設計とそのI/Oの特徴について教えてもらいました。
本シリーズの以前の投稿はこちら :
質問3 : データベースのチューニングのための補助機構についての話がありましたが、それは一体何で、FVPがそこでどんな役割を担うのでしょうか?
OLTPであろうが、データウェアハウスであろうが、データベースのパフォーマンスがビジネスにとって非常に重要であるということは言うまでもありません。その結果としてデータベース管理者はデータベースのパフォーマンスを向上させるための補助機構を利用します。その補助機構の例がインデックスとマテリアライズド・ビュー(MV・訳注:体現ビューとも呼ばれる)です。MVはSQLサーバではインデックスビューとも呼ばれます。
インデックス
インデックスはテーブルを複数の方法でソートできるようにするための補助機構です。これは統合結合などの高速にデータをソートするような参照と操作に対して役立ちます。たくさんの列が含まれているテーブルを考えてみてください。テーブルはディスク上では1通りの方法でしかソートされていません。例として、以下の様な顧客テーブルを考えてみましょう。
CREATE TABLE Customer (
CustID int,
Name Char(20),
Zipcode int,
PRIMARY KEY (CustID));
顧客IDの列で、CustIDがプライマリキーのテーブルです。これはつまり、すべての顧客がそのCustIDの値でユニークに認識されているということです。大抵の場合、このテーブルではこの列に置いてソートされることになります。
ZIPコードが95051の顧客を探すようなクエリを発行したことを考えてください。テーブルはZIPコードでソートされてはいませんので、テーブル内のあらゆる行をZIPコードの値が95051であるかどうか見てゆく必要があり、見つかればその行を積み上げていくことになります。これは非常にコストの高い処理です。こうする代わりに、ZIPコードの行についてインデックスを作成することが可能です。このインデックスはZIPコードでソートされており、そのお陰で検索を早く行えるようになる場合があります。
マテリアライズド・ビュー(体現ビュー)
マテリアライズド・ビュー(MV)はクエリの結果を含むデータベースオブジェクトであるという点で、インデックスとは異なっています。もしも同じクエリが何度も繰り返し実行されるということがわかっているのであればクエリの結果をMV内にキャッシュし、毎回クエリを実行する代わりに、MVを結果として返せばよいのです。
MVを作成するSQL文法の例は以下のとおりです :
CREATE MATERIALIZED VIEW FOO AS SELECT * FROM BAZ WHERE BAZ.id = ‘11’;
上記のSQL宣言ではFOOというマテリアライズド・ビューに「SELECT * FROM BAZ WHERE BAZ.id = 11」というクエリの結果を保存しています。この場合、誰かが「SELECT * FROM BAZ WHERE BAZ.id = 11」というクエリを実行した際にはすでに結果がFOOの中に保存されているので単にFOO内の列を返せばよいのです。今回のこの例は非常にシンプルですが、クエリがどんどん複雑になっていクことを考えれば、MVに結果を保存しておくことが非常にメリットの有ることであると容易に想像できると思います。
これまでのインデックスとMVについてのそれぞれの説明で、ひとつ明らかになることがあります。インデックスとMVの両方は一時的な機構であるということです。つまり、いずれの場合もデータベース内のテーブルと同じようにディスクに永続的なものとして書き込まれる必要があります。結果としてこれらはディスク空き容量を消費しますが、もっと重要なことにこれらへのアクセスは非常に多くのI/Oを必要とする可能性があるのです。これらの補助機構がうまく機能するためには、結局良好なストレージパフォーマンスがキーとなるということなのです。
これらの補助機構には多くの制限もついて回ります。まず最初に、多くのディスク空き容量を消費するということ。元としているテーブルと同じ程度の空き容量を消費してしまうこともしばしばです。結果としてメリットよりもオーバーヘッドが大きくなってしまうこともあります。2つ目に、特にMVを利用する場合ですが、MVの再構成の頻度が大きな違いを産みます。これはどういうことでしょう?
先ほど出したMVの例を考えてみましょう。毎日BAZテーブルに新しい列が追加され、そのうちの幾つかの列がColumn id に 11 という値を設定されているという場合です。言い換えると、BAZにBAZ.id=11と指定して、毎日新しい列が追加されてくるということです。新しい列が追加されると、MV FOOは古くなってしまいます。というのも、もはや正しい行を保存していないからです。ですから、BAZにBAZ.id=11で列が追加される毎に、元となるBAZテーブルだけでなく、FOO MVも再構成する必要があるのです。1つのI/Oが結果として多くのI/Oになってしまうのです。そして、もし誰かが再構成中のMV FOOに対してクエリを実行したとすると、あらゆるストレージのパフォーマンスの問題が発生してしまうのです。
これら両方の補助機構は、どんなクエリを実行するかを理解していれば非常に有効であることを付け加えておきます。もしそうであれば必要なインデックスとMVを生成しておくことができます。しかし、もしこれらの機構を活用できないようなクエリであった場合、パフォーマンスの問題を生じることとなります。本当の問題は事前に実行するクエリをすべて認識できるケースが殆ど無いという事実です。つまり、補助機構は限定的であることが多いのです。
FVPはどのように役に立つか?
フラッシュやメモリ(RAM)のようなサーバサイドリソースを利用する場合、元としているテーブルへの書き込みもWrite-Backモードによって早くなりますが、元となっているこれらのテーブル上に構成されているMVの再構成も早くなります。これはクエリのパフォーマンスは良くなり、高い同時並行性とより良い拡張性を意味します。
FVPはアドホックなクエリの実行も早くすることが可能です。既存のインデックスやMVがクエリ用できないような場合であっても、FVPがフラッシュやメモリ(RAM)のようなサーバサイドリソースにこれらの元となるテーブルを保持することで、アクセスがはるかに早くなります。
上記のポイントはこれまでのように多くのインデックスやMVを作成する必要がないということです。コレによってストレージのキャパシティの観点からも、そしてデータベースを管理し、稼働させるという運用の観点からも大きな節約が実現されます。
Part 4 もすぐに来ます!
記事担当者: マーケティング本部 三好哲生 (@pernixdata_netw)