XMLDBへは正規化して格納する
XMLDBにデータを格納するときは、XMLを正規化(normalize)し、データサイズをなるべく小さくし保存することが推奨されます。XMLの正規化とは、論理的にXMLが同一であるということを保証したうえで、人が読みやすいようにXMLに付加された改行、インデント(半角スペース、タブ、改行)を取り除いたり、要素値が空値の場合で開始タグと終了タグがある場合に、終了タグ(<タグ名/>)のかたちに変換する処理のことをいいます。
正規化により、データベース全体の物理データサイズが減少し、フラグメンテーションによる性能の劣化などをあらかじめ防止することができます。またデータの転送量が減少するので、ネットワークへの負荷も軽減できます。
アプリケーション開発時の注意点
XMLの解析方式による違い
XMLアプリケーションを開発する際に最も注意するべき点は、XMLを解析する際のXMLの処理方式でしょう。以下の表にXML操作方式別の特徴と、デメリットをまとめました。
処理方式名 | 特徴 | デメリット |
DOM | XMLすべてをメモリ上にツリー形式で保存するのでXMLへのランダムアクセスが可能。 | メモリを多く消費する。 |
SAX | XML要素をシリアルに解析し、XMLエンティティ出現イベントの発生ごとにパーサからイベントを受け取る。メモリの使用量が少ない。 | プログラミングが複雑になることがある。 |
StAX | DOMとSAXの中間方式。カーソルでXMLのランダム操作が可能。メモリの使用量もDOMに比べて少ない。 | あまり普及していない。 |
アプリケーションの要件にもよるとは思いますが、上記3つの中では、StAXを採用するのが今後は最もバランスが良いでしょう。DOMを使用する際は、XMLをパースする負荷、メモリ消費量が大きいので、注意が必要です。使用する場合は、DOMの解析実行頻度、処理同時並行性などを考慮する必要があるでしょう。
DOMツリーとJAXBオブジェクトツリーのメモリー使用量比較
第4~6回の「XMLDBとJavaAPI、JAXB2.0を活用したWebアプリケーション開発」(設計編、APIチュートリアル編、実装編)で、JAXBを用いたXMLアプリケーションを開発する手法を説明しました。JAXBもDOMと同様、XMLのデータ構造をツリー構造に保持して操作しますので、メモリーの使用量が気になるところです。ここでは同じXMLデータをDOM形式で保持した場合とJAXBのオブジェクトで保持した場合のメモリーサイズを比較してみました。
使用したXML
以下に検証に使用したXMLを示します。第4~6回で使用した商品のXMLと同一です。実際のXMLは、インデントされておらず正規化されたものを使用しました。
<?xml version="1.0" encoding="UTF-8"?> <item item_code="Cen001"> <item_name>次世代型扇風機ハリケーン</item_name> <price>5000</price> <description> <caption>夏をより快適に、健康に過ごすために、 開発された次世代型扇風機です。人類の健康を害してきたエアコンの時代は 終焉を迎えます。</caption> <header>夏には大ブレーク必至。品切れ必至!!</header> <footer>今年の大ヒット商品として年末にはクローズアップされます。 </footer> </description> <option_name>サイズ</option_name> <options> <option>特大</option> <option>大</option> <option>中</option> </options> <reg_date>2007-06-16T17:51:43.500+09:00</reg_date> </item>
検証方法
以下のJavaプログラムを使用して、XMLを格納したオブジェクトの生成前後のヒープメモリサイズを測定し、前後のメモリサイズの差分によってオブジェクトのサイズを計測しました。
public static void main(String[] args) throws Exception{ // XMLストア Session clientSession = XlnClientSessionFactory.getSession(); XMLStore xmlStore = clientSession.getXMLStore( "ec_item_xmlstore" ); // バインダドキュメントの取得 XMLDocument xmlDoc = (XMLDocument)xmlStore.getFile( "/items/item_container.bnd" ); // XQuery実行 String xquery = "for $item in /MultiDoc_Container/item\n" + "where $item/@item_code='Cen001'\n" + "return $item"; XQuery xQuery = clientSession.createXQuery( xquery ); xQuery.execute(xmlDoc); // XQuery結果の取得 XQuerySequence results = xQuery.getResults(); XQuerySequenceIterator iter = results.getIterator(); JAXBContext jc = JAXBContext.newInstance( Item.class ); Unmarshaller u = jc.createUnmarshaller(); XQueryItem xQueryItem = iter.nextItem(); Node node = (Node)xQueryItem.getValue(); Runtime rt = Runtime.getRuntime(); // オブジェクト取得前 long befMem = rt.totalMemory() - rt.freeMemory(); Object obj = u.unmarshal( node ); // オブジェクト取得後 long aftMem = rt.totalMemory() - rt.freeMemory(); // メモリサイズ System.out.println( "JAXB Memory:" + ( aftMem - befMem ) ); }
Session clientSession = XlnClientSessionFactory.getSession(); XMLStore xmlStore = clientSession.getXMLStore( "ec_item_xmlstore" ); XMLDocument xml = (XMLDocument)xmlStore.getFile( "/items/Cen001.xml" ); Runtime rt = Runtime.getRuntime(); // オブジェクト取得前 long befMem = rt.totalMemory() - rt.freeMemory(); Document doc = xml.getDOMDocumentNode(); // オブジェクト取得後 long aftMem = rt.totalMemory() - rt.freeMemory(); // メモリサイズ System.out.println( "DOM Memory:" + ( aftMem - befMem ) ); clientSession.release();
測定結果
測定結果を以下の表に示します。
検証ケース | メモリ使用量 |
DOM | 784008 byte |
JAXB | 173520 byte |
JAXBのオブジェクトの方が、使用メモリが少ないという結果になりました。
考察・結論
同一のXMLをDOMオブジェクトとJAXBのオブジェクトに格納した場合は、DOMオブジェクトに格納した場合の方がメモリを多く使用しました。これは、DOMオブジェクトの方がXMLの階層構造など、XMLに関する情報をオブジェクト内に格納しているためと考えられます。このようにDOMとJAXBは、同じようにXMLデータをオブジェクトのツリー構造で格納するにしても、JAXBの方が、メモリ消費量が少なく、かつデータ操作のプログラミングもしやすいというメリットがあるので、DOMとJAXBであれば、JAXBの採用をお勧めします。
XMLデータの構造について
XMLDBの検索時に十分な性能を引き出すために最も重要なことを1つ挙げるとしたら、インデックスを適切に使用することでしょう。いくらXMLDBがスキーマレスという特徴を持つといっても、ただ単にwell-formed(整形式)でさえあればどのような構造のXMLでも格納してよいというわけではありません。十分な性能を得るためには、XMLのデータ構造も適切に設計する必要があります。
ただしXMLのデータ構造で、どのようなものが良いとは一概には言えません。それは、インデックスの種類や性質、検索処理別の性能の良し悪しについては各XMLDB製品ごとに異なるからです。開発の中で使用する製品のインデックスの特徴を把握し、検証を繰り返すことによって、性能を引き出していくという作業が必要になるでしょう。
まとめ
本稿では、XMLDB使用時のパフォーマンスに関する注意点として、XQuery、XPathを記述する際の注意点、そしてアプリケーションを開発する際の注意点について、実際に測定し検証しました。今後、XMLDBが世の中に普及していくにつれ、パフォーマンスチューニングに関する情報も蓄積されていくと思われます。
本稿までで7回にわたって、XMLDBについて、Cyber Luxeonを使用して説明してきました。一般的に、何か新しいシステムを開発するといった話がある場合に、RDBをバックエンドDBとして採用されることが暗黙的に前提となっています。
しかし今後システムへの要求は一層複雑化していきます。複雑なデータ構造を持つシステムをRDBで開発するという前提で見積ると、多くの時間がかかってしまうというような場合にも、XMLDBでの開発を検討すると、RDBよりも少ない時間で開発ができるという場面が考えられます。
本連載が、XMLDBの採用をこれから検討する方々、そしてXMLDBをシステムのバックエンドソリューションの1つとして考えている方々の一助となれば幸いです。
参考資料
- 『Cyber Luxeon ハンドブック』 サイバーテック社
- 『XMLデータベース入門』 山田祥寛 著、翔泳社、2006年4月