前回は,FINDSPOTの転置インデックスの構造について説明しました,今回はこの構造に至った経緯などについて解説します。
ブロックの拡張問題
前回,転置インデックスのブロックは次のような構造になっていることを説明しました。
表1 FINDSPOTの転置インデックスのブロック構造
| レコード位置 | 内容(8バイト) |
|---|---|
| 0 | ブロックサイズ |
| 1 | 見だし語 |
| 2 | データ1(文書ID:出現位置) |
| 3 | データ2(文書ID:出現位置) |
| 4 | データ3(文書ID:出現位置) |
| 5 : : : |
データ4(文書ID:出現位置) : : : |
このブロックには,ブロックサイズがいっぱいになるまで(空きレコートが存在する間)は,データを詰め込むことができますが,ブロックが溢れてしまって,これ以上データが格納できない場合にどうするかという課題があります。
転置インデックスの作成当初は対象とする文書数が少ないので,転置インデックスに登録するデータ量は少ないのですが,だんだん登録する文書数が増えていくと,転置インデックスに登録しなければならないデータ量も大きくなっていきます。必然的に,特定のN-gramに関する転置インデックスのレコードが溢れることになり,この時にどのように対処すべきかという問題が発生するのです。
FINDSPOTの初期の実装
FINDSPOTの初期の実装では,ブロックが溢れたら,続きのデータを格納するために新たに別のブロックを作成する方式を採っていました。この時,続きのデータ用のブロック位置に関する情報は,ブロックの第2番目のレコードに格納していました。
表2 初期のFINDSPOTの転置インデックスのブロック構造
| レコード位置 | 内容(8バイト) |
|---|---|
| 0 | ブロックサイズ |
| 1 | 見だし語 |
| 2 | 次のブロック位置 |
| 3 | データ1(文書ID:出現位置) |
| 4 | データ2(文書ID:出現位置) |
| 5 | データ3(文書ID:出現位置) |
| 6 : : : |
データ4(文書ID:出現位置) : : : |
最初に作成するブロックは16レコード分です。この時,ブロックサイズ,見だし語,次のブロック位置のために3レコードを消費するので,都合13レコード分がデータ用に利用できます。このブロックには13個分のデータを書き込めますが,次に14個目のデータを同じN-gramに関して書き込む必要が生じたら,新たなブロックを作成して,14個目のデータを書き込むという寸法です。新たなブロックの転置インデックス内の位置は,元のブロックの第2レコードに書き込むことで,検索の際には,このチェーンを辿って次のブロックを参照できます。
また,ブロックのサイズに関しては,最初は16レコード分のブロックサイズ(128バイト)とし,続きのデータ用のブロックは5個ごとにサイズを倍に拡張するというアルゴリズムを使用していました。次の表は,このブロック拡張によって,トータルで何個のデータが格納できるかを示したものです。
表3 ブロック数とデータ数の関係
| ブロック数 | レコードサイズ | 格納できるデータ数 |
|---|---|---|
| 1 | 16 | 13 |
| 2 | 16 | 26 |
| 3 | 16 | 39 |
| 4 | 16 | 52 |
| 5 | 16 | 65 |
| 6 | 32 | 94 |
| 7 | 32 | 123 |
| 8 | 32 | 152 |
| 9 | 32 | 181 |
| 10 | 32 | 210 |
| 11 | 64 | 271 |
| 12 | 64 | 332 |
| 13 | 64 | 393 |
| 14 | 64 | 454 |
| 15 | 64 | 515 |
| 16 | 128 | 640 |
| 17 | 128 | 765 |
| 18 | 128 | 890 |
| 19 | 128 | 1015 |
| 20 | 128 | 1140 |
| 21 | 256 | 1393 |
| 22 | 256 | 1646 |
| 23 | 256 | 1899 |
| 24 | 256 | 2152 |
| 25 | 256 | 2405 |
| 26 | 512 | 2914 |
| 27 | 512 | 3423 |
| 28 | 512 | 3932 |
| 29 | 512 | 4441 |
| 30 | 512 | 4950 |
| 31 | 1024 | 5971 |
| 32 | 1024 | 6992 |
| 33 | 1024 | 8013 |
| 34 | 1024 | 9034 |
| 35 | 1024 | 10055 |
| 36 | 2048 | 12100 |
| 37 | 2048 | 14145 |
| 38 | 2048 | 16190 |
| 39 | 2048 | 18235 |
| 40 | 2048 | 20280 |
| 41 | 4096 | 24373 |
| 42 | 4096 | 28466 |
| 43 | 4096 | 32559 |
| 44 | 4096 | 36652 |
| 45 | 4096 | 40745 |
| 46 | 8192 | 48934 |
| 47 | 8192 | 57123 |
| 48 | 8192 | 65312 |
| 49 | 8192 | 73501 |
| 50 | 8192 | 81690 |
| 51 | 8192 | 89879 |
| 52 | 8192 | 98068 |
| 53 | 8192 | 106257 |
この表によると,1000個のデータを格納するには19個のブロック,1万個のデータを格納するには35個のブロック,10万個のデータを格納するには53個のブロックが必要になることがわかります(表中色のついた箇所)。
このブロック数を拡張する方法は,使用されていない空きレコードが少ない(最大でも最後に作成したブロックの空きレコード分)ことや,データを追記する際の処理が軽くて済むというメリットがあります。実際に使用してみたところ,転置インデックスの作成スピードは十分でしたが,検索性能に関してはもうひとつ満足のいくものではありませんでした。

