Namazu-devel-ja(旧)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
New data structure
- From: Satoru Takabayashi <satoru-t@xxxxxxxxxxxxxxxxxx>
- Date: Sun, 03 Dec 2000 22:45:15 +0900
- X-ml-name: namazu-devel-ja
- X-mail-count: 01115
備忘録を兼ねて。
ここ 1か月ほど Namazu 3.0 の開発を中断して Sary
<http://sary.namazu.org/> の開発に専念していました。
そろそろ Namazu の開発に戻らないといかんなあ、と考えていたと
ころ、Sary で使っているデータ構造 Suffix Array を用いれば、
インデックスの更新を劇的に速くできることに気づきました。
現在の Namazu: (インデックスの更新が遅い)
構造:
辞書 文書IDのリスト
---------- -------------
ashore 1 3 5 6
burps 2 4 5 7 9 ...
epsilon 1 2 6
retried 3
telegraphs 7 8
構成ファイル:
* NMZ.w - 辞書 (NMZ.wi を用いて 2分探索できる)
* NMZ.wi - NMZ.w にアクセスするためのインデックス
* NMZ.i - 文書IDのリスト
* NMZ.ii - NMZ.i にアクセスするためのインデックス
なぜ更新が遅いのか?
新しい文書を追加してインデックスを更新する際に、新しい単語と
それに対応する文書IDのリストを既存のインデックスに挟み込んで
全体を書き直す必要があるから。
もし NMZ.wi? と NMZ.ii? が合計で 100 MB なら、文書を 1つ追加
してインデックスを更新するだけで、 100 MB 分のファイルを書き
換えないといけない。だから遅い。
新しいデータ構造:
構造:
辞書 文書IDのリスト
---------- -------------
ashore 1 3 4
burps 2 4 5 7
epsilon 1 2 6
retried 3
telegraphs 5 6
あれれ、同じじゃないか!?
構成ファイル:
* NMZ.w - 辞書 (NMZ.wi を用いて 2分探索できる)
* NMZ.wi - NMZ.w にアクセスするための Suffix Array (ここだけ違う)
* NMZ.i - 文書IDのリスト
* NMZ.ii - NMZ.i にアクセスするためのインデックス
新しいデータ構造では、NMZ.w へのアクセスに Suffix Array を用
います。これまでと同じように NMZ.w は 2分探索で検索できます。
NMZ.wi の大きさは、従来のそれと同じです。
なぜ更新を速くできるのか?
新しい文書を追加してインデックスを更新する際には、新しい単語と
それに対応する文書IDのリストを単純に既存のインデックスの末尾
に追加します。そして、Suffix Array である NMZ.wi *だけ* を書
き換えます。
もし NMZ.wi? と NMZ.ii? が 100 MB だとしても、文書を 1つ追加
してインデックスを更新する際には NMZ.wi (せいぜい 1MB) だけ
を書き換えればいい。
古いデータ構造では「新しい単語とそれに対応する文書IDのリスト
を既存のインデックスに挟み込んで全体を書き直」すという複雑な
処理が必要で、未だに微妙なバグが混入しているようですが、新し
いデータ構造では更新が単純なのでそういった心配はありません。
なぜ NMZ.wi だけを書き換えればいいのか?
「新しい単語とそれに対応する文書IDのリストを単純に既存のイ
ンデックスの末尾に追加」すると、次のようなファイルができあ
がります。見ての通り、辞書の並びが崩れてしまいます。
辞書 文書IDのリスト
---------- -------------
ashore 1 3 4
burps 2 4 5 7
epsilon 1 2 6
retried 3
telegraphs 5 6
追加→ ashore 8 9
追加→ burps 8
追加→ epsilon 9
では、どうやって検索をすればいいのでしょうか? 簡単です。
Suffix Array を用いれば、ソートされていない辞書でも 2分探索
で検索できるのです。重複した単語のエントリは検索時にマージ
します。
欠点:
インデックスの更新を繰り返していくと、重複した単語のエントリ
が増えていきます。 `of' のような頻出単語は特に顕著でしょう。
例:
辞書 文書IDのリスト
---------- -------------
:
of 1 3 4
of 5
of 6 8
of 9
:
注意: 実際の辞書はソートされていないが Suffix Array を通す
と見かけ上、ソート済みに見える
検索時には、これらの重複したエントリをマージする必要がありま
す。これが欠点です。しかし、このコストはそれほど大きくないと
思います。
検索速度の低下が気になるようであれば、毎晩あるいは週に 1度と
いった間隔で「インデックスの掃除 (全体をマージして並べ直す)」
すればいいでしょう。この処理は Suffix Array を使って簡単に書
けます。
実験:
25万行、約3.5 MBの NMZ.w に対して Suffix Array を行単位で作
成する。Celeron 500 MHz + 256 MB の計算機なら約 1秒強。
% time mksary -ql NMZ.w
1.09s user 0.03s system 91% cpu 1.22s total
その他の処理を含めて、インデックスの更新は数秒でできそうです。
この速度ならメールを取り込んだタイミングでどんどんインデック
スを更新していっても平気でしょう。
結論:
* 新しいデータ構造ではインデックスの更新が劇的に速くなる
* ただし、更新を繰り返すにつれ検索の性能は徐々に遅くなる
* 定期的に「インデックスの掃除」をすれば検索性能は回復する
* 新しいデータ構造は扱いが単純なのでバグが混入しにくい
* インデックスの大きさは今までのまま
p.s.
このアイディアはシャワーを浴びているときに突然、思いつきまし
た。馬車から降りるときに大発見をした、というポアンカレの逸話
に似ていますね。(僕の場合は大発見でもないが)
--
高林 哲 (Takabayashi, Satoru)
http://namazu.org/~satoru/