Liner Note

情報(ユーザー中心デザイン・ユーザビリティ)と技術(ウェブプログラミング・ウェブサービス)についてのメモ書き

要約:伝統的なRDBMSのレコードにXMLファイルを突っ込んで、XMLデータベースチックに扱えるようなライブラリを使って楽してみます

最近大量の情報を扱うようになってから、MySQLやらSQLiteなどのRDBMSを触っているのですが、どうにも慣れません。

以前から小規模な設定は、SimpleXMLで書いたり読んだりしていまして、データベースなぞに触らなかったものですから、その直感的な操作性に味を占めてしまうと、前時代的なSQLのクエリをちくちく発行する気にはどうにもなりません1 。それにバイナリで中身が見られないというのは、全てがテキストエディタで覗けてなんとかなるというのに慣れた身にはどうにも不安すぎます。

何年か前からXMLでデータを管理するXMLデータベースというのも出ていて、Apache Xindiceなんかはオープンソースでの開発が進んでいるそうですが、一般的なレンタルサーバにおいてPHPで扱えるとなると、選択肢はどうもないようです。

そこで、SQLiteを使ってXMLデータベース的な事をやってみました2 。方法はまぁ誰もが思い
つくとは思いますが、BLOB型のレコードにXMLファイル文字列をそのまま突っ込んでIDつけてるだけです。それをクラスライブラリを介して、透過的に扱おうという案配です。

パフォーマンステスト

で、とりあえず、パフォーマンステストとして定番らしい郵便番号→住所変換で実行時間を測定してみます(元データは郵便事業会社で公開されています)

実験内容
Aにはデータを郵便番号、地名、番地名など細かい住所をそのままRDBの構造として格納、BにはこれらをXMLとして表現したものをそのまま挿入したものを挿入します。それぞれ郵便番号を指定して住所に変換する時間を測定します(レコード数は118,576件)
Aの方法
実行時間:0.04671秒(5回実行平均)
メモリ最大使用量:約995KB
Bの方法
実行時間:0.17422秒(5回実行平均)
メモリ最大使用量:約1009KB

標準的なRDBに比べ4倍遅いという結果になりましたが、個人的には許容量なので今後はこれで開発していこうかなと思います。今のところは10万件レベルのデータを扱うことはそんなにないですし、数千件程度の小規模な場合ならBの方法でも0.01秒程度で実行できます。

生のXMLファイルをずらっと並べた上で、ファイル読み込み→SimpleXMLを使って検索なんかすると、メモリをバンバン食う上にスケーラビリティが皆無に等しいのですが、この方法だとある程度は持ちこたえられます。パフォーマンスやスケーラビリティを気にする人は間違っても使ってはいけません。加えてテーブルを1個しか持てませんが、増やしたい場合はデータベースファイルを増やせば良いだけなので特に気にしてません。

取扱説明書

初期データ入力
コントローラ側で、データ元のXMLがあるフォルダとDBのファイル名を指定します。DBファイルは事前に空ファイルを”ファイル名.db”という名前で作っておき、XMLがあるフォルダと共に書き込み可能にしておきます。コントローラのURIに construct というクエリを付けて実行するとデータ入力が始まります。
データ取得

searchメソッドで検索結果を取得を取得できます。引数は3つあり、順に”検索語”, “検索方法”, “検索対象の要素がある場所”です。

検索方法が取る値はall(全文検索), parts(部分一致), full(完全一致), prefix(前方一致), suffix(後方一致)の4つです。検索対象の要素がある場所はSimpleXMLを使うときのようにノードのパスを指定します、全文検索の際はこの引数は無視されます。

正常にデータが取得できれば、XMLの配列でデータが帰ってきます(SimpleXMLElement Object型になってます)

サンプルコード(郵便番号→住所の変換)

PHPソースコード
<?php
$db = new XSQLiteManager;
 
// データベースのファイル名とXMLがあるフォルダを指定して読み込む
$db->simplexml_load_db("zipcode", "./data");
 
if ($_GET["zip"]){
  $zip = mb_convert_kana($_GET["zip"], "a");
  if (preg_match("/(\d{3})\-?(\d{4})/", $zip, $q)){
    // 検索を実行してXMLの配列形式で結果を受け取る
    $results = $db->search($q[1].$q[2], "full", "zip");
    if ($results){
      $address = $results[0]->name. $results[0]->local;
      echo "郵便番号(". htmlspecialchars($zip) .")の住所は". $address ."です";
    } else{
      echo "検索語に当てはまる検索結果が見つかりません";
    }
  } else{
    echo "正しい郵便番号(数字7桁)を入力してください";
  }
}
 
 
?>
データ追加
XMLデータ文字列を引数にして insertXML メソッドを実行してください。データベースの最後尾に追加されます。
データ更新
IDとXMLデータ文字列を引数にして updateXML メソッドを実行してください。IDはデータベース上のレコード番号のことで search メソッドを実行したときに帰ってくる結果の配列のキーに書いてあります。
データ削除
IDを引数にして deleteXML メソッドを実行してください。

デモとダウンロード

郵便番号検索デモサイト

ダウンロード
データベース一式 (20MB)
ライセンス
GNU General Public License(郵便番号データの著作権は郵便事業会社にあると思うので除外)
  1. なにしろPHP5だと simplexml_load_file で設定を読み込んで、目的の項目を選ぶという2行のコードですむわけですから。RDBMSもフレームワーク附属のライブラリを使えば楽になるのかもしれませんけどフレームワークを使わない場合もあるわけで[戻る]
  2. SQliteにしたのは必要なファイルが1つにまとめられていて環境移行がやりやすいためです[戻る]

Popularity: 3% [?]

キーワード:

似たもの記事

読者の皆さんの反応サイト内コメントの更新情報(RSSフィード)

読者のコメント

0

ブックマークコメント

1

他サイトの関連記事

1

読者のコメント

コメントはまだ寄せられていません

はてなブックマークでつけられたコメント

fuktommyさんのプロフィール画像  fuktommy
なんかXMLによるDBって信用できないんだよなあ。
ほとんど気分の問題でしかないんだけど。

他サイトの関連記事

  1. ウェブサイト

    ぱふぅ家のホームページ

    投稿日時
    2009年10月01日
    15時ごろ
    Comment No
    #1

    PHP+SQLite:あいまい検索

    PHP5とSQLiteを使って、あいまい条件検索(LIKE式)を使ったプログラムを作る。


トラックバックとは
この記事に言及したサイトをこちらに掲載する仕組みをトラックバックと言います。ここでは、このサイトに頂いたトラックバックを一覧表示しています。
トラックバックしてくださる方へ
この記事への言及がない記事など、トラックバック受信方針に沿っていないものは、読者にお見せしても仕方ないこともあり削除させていただいることをご了承ください。
トラックバックを受け取るためのURI

コメント書き込みフォーム

  • メールアドレスはウェブ上で公開したり、連絡以外で使うことはありません
  • コメントを公開したくないが、作者に連絡を取りたい場合は メールで連絡してください
  • 本文中にHTMLコードは使用できません(URLはそのままお書きください)