XMLデータベース開発方法論(6) Page 4/5

変化に強いXMLデータベース設計とチューニング


川俣 晶
株式会社ピーデー
2005/11/19

データ構造の最適化の必要性

 さて、ここからは話題が変わる。XMLデータベースの現実を示すとすれば、やはり「性能」は重要なファクターとなる。われわれは無限のCPUパワーを持ち合わせてはおらず、巨大なデータを前にしたとき、常に性能不足の幻影に怯えねばならない。

 これに立ち向かうということは、ときとしてあらゆるものを投げ出す覚悟を決めた総力戦となる。あるべき理想論、きれい事は放棄され、汚い性能向上テクニックがシステムの主導権を握ることもあるだろう。

 これはXMLデータベースでも例外ではない。いや、より正確にいえば、XMLデータベースではより強く要求される問題といえるだろう。XMLデータベースには、しばしば非常に多くのデータを扱うニーズが突き付けられるためである。例えば、社内の複数のデータベースを集めたデータベースを作り、これを検索したい……というようなニーズでは、個々のサーバよりも大きなデータを扱うことが要求される。より大きなデータを処理するには、それに見合った性能向上が要求されるが、それにもかかわらず、XMLデータベースは従来のRDBよりも圧倒的に速いわけではない。

 つまり、XMLデータベースでも性能は問題にされ、性能を意識した設計は大きな意味を持つ。いい換えればデータ構造は性能を向上させるために最適化させる価値がある。

準備段階

 XMLデータベースに対するクエリなどの処理が十分な時間で処理できない場合、それを改善するための方策を検討することになる。例えば、ハードウェアの性能向上、サーバの増設、使用するXMLデータベースソフトをより高速なものに置き換えるといった選択肢も、検討の対象になるだろう。しかし、ここではデータ構造の最適化に限って話を進める。

 データ構造の最適化には、2種類がある。1つは、追加/削除やクエリの処理から無駄を省くことである。もう1つは、主にクエリ性能を向上させるためにデータ構造をより高速に処理できるように変更することである。前者は、XMLデータベースの種類に関係なく、どのソフトを使う場合でも同じルールが適用できるものである。しかし、後者はXMLデータベースの構造や実装に強く依存しているため、一般論として方針を示すことができない。例えば、「NeoCore XMS」は確定されたパスを探す場合にはクエリを高速に実行できるが、要素内容のテキストの部分文字列を検索するようなクエリには弱いとされる。一方、「Interstage Shunsaku Data Manager」(以下、Shunsaku)は、単純なクエリでも多くの時間を要するが、クエリが複雑化してもクエリに要する時間は変わらないとされる。このような性質の違いがあるため、クエリ性能を向上させるためのデータ構造の変更は、個別のXMLデータベースソフトごとに別の対応が求められることになる。

 つまり、データ構造の最適化に取り組む前の準備段階において、使用しているXMLデータベースのクエリの得意なパターンと不得意なパターンを把握していく必要がある。それを知らずして、性能向上を試行錯誤するのは効率が悪過ぎる。とはいえ、細かい機能性に関する得意・不得意の差は、事前に調べ尽くすことは難しいだろう。それらは実際の作業を通じて試行錯誤してもよいと思う。

 ここでは、主に前者(追加/削除やクエリの処理から無駄を省くこと)について説明を行っていく。

追加/削除の最適化

 明らかに無駄な構造の削除は、すでに述べたXMLデータベースのリファクタリングと重複の多いトピックといえる。同じ情報の重複や、不必要にまわりくどい間接的な表現などを改めるだけで、クエリ性能が上がる可能性がある。しかし、ここでは追加/削除について、取り除き得る無駄の例を見てみよう。

 例えば、人物の親子関係を、そのまま要素の親子関係に当てはめて表現することができる。以下はそれを行った例である。

<人物>
  <名前>黒騎士ファウスト<名前>
  <子>
    <人物>
      <名前>星野鉄郎<名前>
    </人物>
  </子>
</人物>

 この例は、設計として突っ込みどころがいろいろあるのだが、それはさておき、ここでは追加/削除のコストの問題について見ることにする。

 さて、「黒騎士ファウスト」は、息子との対決に敗れ、宇宙の藻くずとなってしまったとしよう。それに応じて、このデータが含まれるXMLデータベースから「黒騎士ファウスト」の情報を削除する必要性が生じたとする。基本的には、「黒騎士ファウスト」について記述された「人物」要素を削除する処理が要求されているわけである。しかし、実はそれだけではうまくいかない。なぜなら、この削除は、「黒騎士ファウスト」について記述された「人物」要素のすべての子孫を削除することになるためである。そして、その中には「星野鉄郎」について書かれた「人物」要素も含まれている。しかし、「黒騎士ファウスト」に勝利して父を乗り越えた息子、「星野鉄郎」はまだ生きていて、削除の対象にはなっていない。

 この場合、「黒騎士ファウスト」の情報を削除するという処理は、削除するという処理のほかに、「星野鉄郎」についての情報を新たに追加し直す(あるいはツリーの中で、「黒騎士ファウスト」の子の位置から別の場所に移動させる)という処理を必要とする。

 同様の問題は、追加の処理を行う場合にも発生する。例えば、以下のような情報が記録されていたとする。

<人物>
  <名前>ピエロ・ボルネーゼ<名前>
</人物>

 この状態で、実はピエロ・ボルネーゼとは、本来レオール・レオンハルトという名前であり、レオンハルト14世の息子であることが明らかになったとする。この結果を反映して、以下のように情報を追加することを考えてみよう。

<人物>
  <名前>レオンハルト14世<名前>
  <子>
    <人物>
      <名前>レオール・レオンハルト<名前>
    </人物>
  </子>
</人物>

 ここで、名前の変更はさしたる問題ではない。単なるテキストの置き換えは、ほかのノードに影響を及ぼさない。しかし、親についての情報を追加するためには、単に「レオンハルト14世」について記述する「人物」要素を追加するだけでは済まないことが分かるだろう。ピエロ・ボルネーゼ(レオール・レオンハルト)についての「人物」要素を削除したうえで「レオンハルト14世」の情報の子として追加する(あるいはノードをそこに移動させる)という処理も必要とされる。

 このような設計は、ある情報に到達するためのパスが変わってしまうという意味でも、問題がある。例えば、ある情報を検索し、それが含まれるノードのパスが分かった場合、その情報が削除されない限り同じパスにそれが見いだせるという前提を取ることができれば、効率の良い処理が実現できる。しかし、このような追加/削除処理は、パスそのものが「/人物」から「/人物/子/人物」へ、あるいは逆の方向に変化してしまうことを意味する。

 このような問題を回避するには、以下のような原則を取るとよい。

  • 追加、削除の対象となる単位で情報をグループ化する(前々回の「関連する情報をグループ化する」を参照)
  • 個々の情報グループを子として持つコンテナとなる要素を設ける
  • コンテナは常に存在し、パス上の位置も移動させないようにする
  • 個々の情報グループ間に親子関係を持たせない(親子関係は、コンテナと情報グループの間でのみ発生するようにする)

 以上のような原則を貫くことで、追加、削除に対する無駄を省くことができる。この例でいえば、親についての情報を記述するノードの下に子に関する情報のノードはないので、親の情報の削除は、子の情報に影響を及ぼさない。

 なお、上記のような親子の関係の例では、別の手段で誰が誰の子であるかという情報を持たせる必要がある。それについては、いろいろなトピックがあるのだが、ここでは残念ながら誌面の都合で割愛する。(次ページへ続く)

4/5

 Index
XMLデータベース開発方法論(6)
変化に強いXMLデータベース設計とチューニング
  Page 1
・前回のおさらいと今回のテーマ
・ノイズまみれのシステム
  Page 2
・変化に追従する柔軟なデータ構造
・拡張のためのスタブ
  Page 3
・YAGNI再び
・要素と属性の問題再び
・「ゼロ時間変換」を行うか否かの選択
・データベースのリファクタリング
Page 4
・データ構造の最適化の必要性
・準備段階
・追加/削除の最適化
  Page 5
・クエリの無駄を省く
・クエリの効率アップ
・「標準」に魂を奪われるな!
・連載の終わりに


XMLデータベース開発論


Database Expert フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Database Expert 記事ランキング

本日月間