Linterには、
の3つのバージョンが存在する。EnterpriseとEmbeddedは基本的に同じソースコードで、Microのみ別ソースとなっている。つまり、EmbeddedはEnterpriseから機能の削り込みを行ったものなのである。従って、これからEmbeddedを前提に説明を行うが、アーキテクチャについてはEnterpriseについても当てはまる。
Linterの特徴として、いわゆるコンパクション(Compaction)に相当する操作が基本的に存在しないことが挙げられる。
図1は、一般的なRDBのテーブル操作を示したものだが、一般にRowのDELETEをしたからといって、すぐに全体を詰めるのは無駄が多い。そこでDELETEしたRowの空間はそのまま残しておき、一方でRowのINSERTはテーブルの下側をどんどん拡張してゆく形で行われる。結果として、INSERT/DELETEを繰り返すと、テーブルは無駄に肥大化することになる。そこで定期的にこれを詰める作業(コンパクション)が必要になる。要するにガベージコレクションの一種で、RDB内部でトリガなどを使って定期的に実施するのが普通だ。
これに対しLinterでは、図2のような動きとなる。
あるテーブルのRowを削除する際、そのRowの場所を別のエリアに記録しておき、Row INSERTの際に先ほど削除したRowの場所を埋めるような構造となっている。このため、基本的にはコンパクション操作なしに、テーブルのサイズが常に最小限に保たれる構造となっている。この方式を採用することにより、
というメリットが生まれ、メモリサイズにゆとりがないことが多い組み込み系や応答時間の制約があるリアルタイム系システムでも利用できる可能性が広がる(注)。
これは特殊な手法ではなく、メモリやディスクサイズが厳しい環境下のアプリケーションでは普通に行われてきた。RDBではテーブルの効率よりもパフォーマンスが優先されるほか、もともとデータベースサーバには十分なメモリとストレージを用意することが鉄則であることから、最近ではこうした手法を使う製品は多くない。
リアルタイム系の特徴としては、Linterはプリエンプション(Preemption)にも対応している。例えば、あるトリガで始まるタスクを特定のOSプライオリティで動かすことも、Linterでは可能である。UNIX/Windows系OSではあまりなじみのない機能だが、リアルタイム系OSは複数のソフトウェアプライオリティを持ち、これを使ってクリティカルな処理の応答時間を保証することが可能になっている。
非リアルタイムOSと非リアルタイムRDBを組み合わせた場合の動作は、図3のようになる。基本的にはRDBもほかのアプリケーションと同一の扱いだから、仮にイベントが発生したとしても、ラウンドロビンなどのスケジューリングにのっとって自分にCPUが回ってくるまで待たなければならない。さらに、RDBにCPUが回ってきても、イベントのハンドリングを始められるのは、RDB内部ですでにキューイングされた処理を順次こなした後になってしまう。
OSをリアルタイムOSにすると、少々乱暴だが図4のようなアプローチが可能だ。RDBをハイプライオリティに割り当ててしまえば、イベント発生時に最優先でRDBが動くので、レスポンスタイムは圧倒的に短くなる。ただしRDB内部での待ち時間は変わらないし、そもそもハイプライオリティでRDBなどを長時間動かすと、システム全体への影響が非常に大きいので好ましい方法とはいえない。
Linterを使用したケースが図5だ。イベントのハンドリングを行うときだけハイプライオリティで動作するが、それ以外は通常のタスクとして動作する。これが一番レスポンスタイムが短く、かつシステムのオーバーヘッドも少ないことは容易に理解できよう。
このほかにも、例えばクエリーを実行した際、通常のRDBは新たなテーブルにResult Setを格納するが、LinterはBV(Bit-Vector)というbit単位のインデックスを持ち、ここからクエリー結果に含まれるRowへのインデックスを張る形でResult Setを保持する。いうまでもなく、この方式はメモリ使用量を最小に抑えられる。
また、Linterにおけるトランザクション機能は、
という2つのジャーナルを作成しており、アプリケーションからコミットを発行されたものについては100%保証をうたっている。しかも、例えば電源断が発生して再起動後に復旧を行う過程そのものもやはりジャーナルを取っている。そのため、「極論すれば、もう1回電源断があっても大丈夫」(鎌田氏)という高信頼性を誇る。
Copyright © ITmedia, Inc. All Rights Reserved.