groonga / grnxx

groonga++
Other
7 stars 0 forks source link

Goroonga で検索結果の受け取りにかかる時間を調べる #153

Closed s-yata closed 9 years ago

s-yata commented 9 years ago

概要

Groonga との連携を検証するため, Goroonga で検索結果の受け取りにかかる時間を調べます.

具体的には,検索結果に含まれるレコード数を調整しつつ,検索結果(ID, Score)の受け取りにかかる時間を計測します. ついでに,カラムの内容を受け取るのにかかる時間も調べます.

検索結果の受け取りにかかる時間が絞り込みにかかる時間と比べて十分に短くなければ, Grnxx と組み合わせても検索時間を短縮するのは難しいということになります.

s-yata commented 9 years ago

データベースの構成

以下のようにしました.

table_create Table TABLE_NO_KEY
column_create Table Body --type Text
column_create Table Length --type Int64
column_create Table RandInt --type Int64
column_create Table RandFloat --type Float
table_create IntIndex TABLE_PAT_KEY Int64
column_create IntIndex RandInt COLUMN_INDEX Table RandInt
s-yata commented 9 years ago

結果

クエリは以下の 2 種としました. Threshold を変更することで検索結果に含まれるレコード数を調整します.

まず,検索結果のサイズを以下に示します.

Threshold OutputAll ID, Score
1 15KB 1KB
10 142KB 12KB
100 1,360KB 108KB
1,000 13,656KB 1,082KB
10,000 138,632KB 10,889KB

次に,検索に要した時間を示します.

Threshold OutputAll ID, Score
1 2ms 1ms
10 5ms 2ms
100 40ms 6ms
1,000 270ms 61ms
10,000 2,674ms 388ms

これらの結果より,本文をまとめて返すとかなり時間がかかることがわかります. 本実験では 100bytes 程度の短い Text なので,より長い Text を使えば,その分だけ時間がかかるものと予想されます.

ID, Score のみを返す場合,本文などを含めた場合よりは短時間で終わります. しかし,レコード数 1,000,000 で 388ms というのは,かなり厳しい数字のように思えます.

Goroonga より得られた結果を Grnxx に渡せる形式に変換し,それを Grnxx で絞り込み,その結果をまた出力用の形式に戻さなければなりません. 絞り込みの条件が単純であれば,おそらく Groonga 側で絞り込みも片付ける方が効率的でしょう.

s-yata commented 9 years ago

参考

参考までに,データベースの構成から索引を取り除いたらどうなるかを示します. 具体的には,以下のコマンドを取り除いただけです.

table_create IntIndex TABLE_PAT_KEY Int64
column_create IntIndex RandInt COLUMN_INDEX Table RandInt
Threshold OutputAll ID, Score
1 167ms 167ms
10 170ms 166ms
100 194ms 175ms
1,000 399ms 206ms
10,000 2,198ms 454ms

索引を取り除いたため,検索は全走査になっているはずです. この結果から, RandInt < Threshold という単純な条件による絞り込みにかかる時間は 160-170ms とわかります(※).

※ ID 昇順に絞り込みできるので,索引を使った後に絞り込みをするケースとは条件が異なります.

さらに,先の結果と併せれば, 1,000,000 万件の ID, Score を受け取るのには 300ms 程度が想定されます. このことから,少なくとも RandInt < Threshold のような単純な絞り込みについては, Groonga 側ですべて片付けた方が効率的になる可能性が高そうです.

s-yata commented 9 years ago

つづき

--output_type msgpack を試してみます.

s-yata commented 9 years ago

Json と Msgpack の比較

索引ありの状態で,以下のクエリについて Threshold を変更しつつ実行時間を計測してみました. 計測したのは結果を受け取るまでで,検索結果のパースなどは含みません. 単純に出力の書式による実行時間の違いを確認しただけです.

Threshold Json Msgpack
1 3ms 3ms
10 8ms 8ms
100 37ms 26ms
1,000 299ms 186ms
10,000 2,802ms 1,976ms

Json より Msgpack の方が速いことを確認できました. Goroonga と Grnxx の連携については復号のコストも関わってくるので, Msgpack がより有利になるのではないかと思います.

さらに,クエリに --output_columns '_id,_score' を加えて ID, Score のみを返すようにすると以下のようになりました.

Threshold Json Msgpack
1 1ms 1ms
10 6ms 2ms
100 15ms 5ms
1,000 47ms 34ms
10,000 427ms 370ms

想定より差が小さいものの, Msgpack の方が少し速くなることを確認できました. 検索自体のコストもあるので,こんなものでしょうか.

ちなみに, Json より Msgpack の方がデータサイズも少し小さくなります. 可読性が必要なく,バイナリによるやり取りで問題ない状況であれば,基本的に Msgpack の方が効率的になりそうです.