DB2 9 を利用したメール・アーカイブ・システムの開発 (4)
ことしもあと・・・
2007年も早いものでもう12月ですね~。
この前まで、「暑い」とか言ってたと思ったら、すっかり寒くなってしまいました。w
この週末は、少し風邪気味だったので、家でおとなしくしていたんですが、結構まわりで風邪とかインフルエンザとか流行っているようなので、皆様お体に気を付けて下さい。
スプールデータの処理について
前回までは、XMLデータベースに定義する表の設計方法について触れました。
このあたりは今でも頭の中ではいろいろなことを考えてるんですが、まだこれといった結論は出ていないし、いろいろと試行錯誤も繰り返しつつ模索しようと思っています。ということで、また思い出したように話題にするかもしれません・・・。
さて、アーカイブの話に戻します。今回の一つ目の話題は、日々蓄積されるメールデータの格納に関してです。
Windowsのサービスに組み込まれたレシーバプログラムは、転送されてくるメールを監視します(監視間隔の初期値は300秒)。受信したメールは、日単位に作成されるスプールフォルダに自動的に格納されます。

下図のように、日付の変わった夜間にスケジュール処理で前日までのデータを処理するのが通常の処理方法となります。

アーカイブを行うだけであれば、デイリーの運用で十分です。
しかし、アーカイブだけではなく、メールデータの有効活用を考えたときは、将来的にリアルタイムの処理が必要になるかもしれません。
オイデスでは、運用パラメータを変更することにより、リアルタイム的な処理も可能です。この場合は、本日のスプールフォルダのデータに関しては、未処理のものだけ抽出してアーカイブします(下図参照)。

リアルタイムの処理は、更に、メールレシーバと連携することにより、スケジュールすることなく、自動的に行うことも可能かもしれません。例えば、ある一定時間を経過してメールの受信があれば、自動的にインポート処理を実行させる機能をレシーバに組み込むのです。
これによってシステムの自動連携なども可能になるかもしれません。
例えば、緊急メールがあれば本人の携帯電話にメールするとか、本人が受信する前に自動的に不要なメールを削除してしまう・・・など、アイデアはいろいろです。
メールデータのインポート処理
今回の二つ目の話題はメールデータのインポート処理に関してです。
当メールアーカイブでは、検索用データとしてのXMLデータを格納する処理と、メールデータそのものを格納する処理の2系統の処理に分けられますが(下図参照)、特にXMLデータのインポートについて説明してみたいと思います。

XMLデータの一括入力については、DB2でサポートしている「インポート・ユーティリティ」を使用しています。これは、CSV形式のファイルを作成して読込処理を行うものです。
下記のようなメリットがあります。
- およそ表のカラム順に格納する値を列挙すればよい
- XMLカラムに読み込ませるXMLファイルは、ファイル名を記載すればよい
- 割と高速で処理が可能
もし、ID列とXML列だけの表であれば、次のような形式のファイル(DELファイル)を作成すればOKです。
ここで、「00014895.xml」は、ファイルの名称です。格納されているパスはコマンドで指定できます。
14895,"<XDS FIL='00014895.xml'/>"当アプリケーションのケースでは、詳細の説明は省きますが、下記のようなファイルイメージになります。(表の各カラムについては第1回のER図と比較してみてください。)
14896,"<XDS FIL='00014896.xml'/>"
20092,"{MAIL_DES値}","<XDS FIL='{XMLファイル名}' />","{MESSAGE_ID値}",
"{IN_REPLY_TO値}","2007/11/12 09:41:46.000000","20071112062356",
0,2524,0,3,0
実行している「import」コマンドは次のようなものです。import from "{delファイル名}" of del xml from "{パス名}"
modified by TIMESTAMPFORMAT="YYYY/MM/DD HH:MM:SS.UUUUUU"
insert_update into "{スキーマ名}"."{表名}"
ここで重要なのが、「insert_update」というキーワードです。これは、「あれば更新し、無ければ挿入して下さい」という意味になります。もし、これ以外を指定するとなると、「replace」となり、意味は「テーブルの全レコードを入替えてください」になります。
つまり現在のデータベースの表にレコードを追加していく場合は、「replace」は使えませんから、必然的に「insert_update」となります。
更に、インデックスの作成により、メールの識別番号や、メッセージIDによって重複不可のデータベースの制約を設けているので、もしそれらが重複したメールをインポートしようと思っても「できませんでしたよ」という警告がログに残ります。
識別番号のほうは、同じファイルの更新なので、運用上は殆ど無いのですが、このメッセージIDの重複に関しては、結構頻繁に発生します。ログファイルに書かれる警告も結構うるさいので、インポートリストから予め除外するような改善を施しました。つまり同一IDの有無をデータベースで確認(フェッチ)して調べてから必要な分だけのDELファイルを作成しています。
前段にSPAMフィルタを設置するようなケースもあるかと思うのですが、このDELファイルを作成する処理の中に、不要なメールはアーカイブしないようにするためのロジックを組み込んでいます。
例えば、「件名の先頭に"[SPAM]"のあるメールを除外する・・・」などの処理を有効にさせることが可能です。
さて、実際に実行しているコマンドは、次のものです。
DB2CMD.exe /c /w /i DB2 -td# -ixf {DDLFile} -z[LogFile]
パラメータの説明は省略しますが、特に「DB2CMD」の「/w」パラメータは重要なので一言。これはプロセスが終了するまで待機してくれるものです。MAGICの外部コールのDOSコマンドの「Wait」に相当しますが、このパラメータを指定しておかないと全然意味がありません。
例えば、後続の処理でログファイルを読み込む必要がある場合等は、これを指定しておかないと、正しくログファイルとハンドルしてくれません。
ログファイルの話題になったので、一言書いておきますが、メールデータの中には、文字コードの関連で、XMLとして不正なデータとなるためにDB2に取り込めないケースが結構あります。それらの内容はログに記載されるので、どのデータがエラーとなったかを記録するための処理を実装しています。
余談ですが、DB2の新しいバージョン9.5では、「インポート」を「ロード」コマンドに置き換えることによって、高速の処理が可能になった模様です。これは、ロードコマンドがログを書き出さないで処理できるようになったためだそうです。
このあたりは実際にやってみようと思っています。
次回は・・・
もう少し早い連載を当初は考えていたのですが、多少、遅れ気味で申し訳ありません。
今回は、なんかいろいろと書いてしまって、ちょっとまとまりがつかなかったんですが、ご勘弁下さい。
次回はいよいよ検索処理の実際について書いてみようと思っています。
