PostgreSQLでn日本語全文検索

: subtitle

LIKEとpg_bigmとPGroonga

: author

須藤功平

: institution

株式会社クリアコード

: content-source

PostgreSQLアンカンファレンス@東京

: date

2015-05-30

: allotted-time

20m

: theme

.

内容

((‘tag:center’)) ((‘tag:large’)) PostgreSQLで使えるn 日本語全文検索方法をn 順に紹介

((‘ ’))

1: LIKE

* メリット
  * 標準で使える
  * インデックス作成不要\n
    (('note:(データ更新が遅くならない)'))
  * データが少なければ十分速い
* デメリット
  * データ量に比例して遅くなる

「少ない」データ?

どのくらいなら少ないのかn ↓n 計測結果と要件で判断

計測

pg_bigmでいろんなデータをn 日本語検索してみよう!n ((‘note:qiita.com/fujii_masao/items/87f1d94ff4d350a718aa’))

* 青空文庫の書籍一覧データ
* 住所データ
* 日本版Wikipediaの\n
  タイトル一覧データ

青空文庫:作品名

* データ:
  * 11,818件
  * 1レコード平均17バイト
* 速度:
  * 6.673ms

((‘wait’)) ((‘tag:center’)) ((‘tag:x-large’)) 十分速い

住所データ:市区町村

* データ:
  * 147,769件
  * 1レコード平均14バイト
* 速度:
  * 70.684ms

((‘wait’)) ((‘tag:center’)) ((‘tag:x-large’)) 十分速い

Wikipedia:タイトル

* データ:
  * 2,461,588件
  * 1レコード平均20バイト
* 速度:
  * 943.450ms

((‘wait’)) ((‘tag:center’)) ((‘tag:x-large’)) 十分速い?

LIKEの計測結果

# RT
delimiter = [|]

件数 | 平均サイズ | 速度

11,818 | 17バイト | 6.673ms
147,769 | 14バイト | 70.684ms
2,461,588 | 20バイト | 943.450ms

((‘tag:center’)) ((‘tag:margin-top’)) ((‘tag:large’)) 十分速いならLIKEでOK!

LIKE以外の選択肢

* pg_bigm
* PGroonga

2: pg_bigm

* メリット
  * データ量が多くても高速
  * ストリーミングレプリケーション可
* デメリット
  * 別途インストールしないといけない
  * インデックス作成が遅い
  * ヒット数に比例して遅くなる

遅い?

((‘tag:center’)) ((‘tag:x-large’)) 計測して確認

((‘tag:margin-top’)) ((‘tag:margin-top’)) ((‘note:備考:’))

* (('note:LIKEでは計測していないがLIKEよりは確実に速い'))
* (('note:LIKEはヒット数に依らずすべて同程度の検索時間になる'))

計測

PGroongaとpg_bigmのn ベンチマーク結果n ((‘note:github.com/groonga/wikipedia-search/issues/2’))

* データ
  * 日本語版Wikipediaの本文
  * 1,846,514件
  * 1レコード平均3777バイト

インデックス作成

# RT
delimiter = [|]

元データの\nロード時間 | インデックス\n作成時間

16分31秒 | 5時間56分15秒

((‘wait’)) ((‘tag:center’)) 遅い?そうでもない?

ヒット数と検索時間

# RT
delimiter = [|]

ヒット数 | 検索時間

361 | 0.107s(('   '))
17,168 | 1.224s(('   '))
22,885 | 2.472s(('   '))
625,792 | 0.556s(*)

((‘note:(*) 検索語が2文字以下ならヒット数が増えても遅くならない’))

((‘note:(*) work_memを10MBに増やしている’))

((‘wait’)) ((‘tag:center’)) 遅い?そうでもない?

pg_bigmの計測結果

インデックス作成時間: 約6時間

# RT
caption = 検索時間
delimiter = [|]

ヒット数 | 検索時間

361 | 0.107s
17,168 | 1.224s
22,885 | 2.472s
625,792 | 0.556s

((‘tag:center’)) ((‘tag:margin-top’)) 遅くないならpg_bigmでOK!

残りの選択肢

* PGroonga

3: PGroonga

* メリット
  * インデックス作成が速い
  * データ量が多くても高速
  * ヒット数が多くても高速
* デメリット
  * 別途インストールしないといけない
  * ストリーミングレプリケーション×

インデックス作成

# RT
delimiter = [|]

元データの\nロード時間 | インデックス\n作成時間

16分31秒 | 25分37秒

インデックス作成:比較

# RT
delimiter = [|]

PGroonga | pg_bigm

25分37秒 | 5時間56分15秒

((‘wait’)) ((‘tag:center’)) ((‘tag:margin-top’)) ((‘tag:x-large’)) 非常に高速

ヒット数と検索時間

# RT
delimiter = [|]

ヒット数 | 検索時間

368 | 0.030s(('   '))
17,172 | 0.121s(('   '))
22,885 | 0.179s(('   '))
625,792 | 0.646s(*)

((‘note:(*) work_memを10MBに増やしている’))

((‘note:(*) 直接Groongaで検索すると0.085s’))

検索時間:比較

# RT
delimiter = [|]

ヒット数 | PGroonga | pg_bigm

368 | 0.030s | 0.107s
17,172 | 0.121s | 1.224s
22,885 | 0.179s | 2.472s
625,792 | 0.646s | 0.556s

((‘wait’)) ((‘tag:center’)) ((‘tag:margin-top’)) ((‘tag:x-large’)) 非常に高速

おねがい

((‘tag:center’)) 同じベンチマークを実行してn 結果を貼ってください!n ((‘note:同じ傾向があるか確認したい’))

((‘tag:margin-top’)) ((‘tag:margin-top’)) ベンチマークの実行方法↓n ((‘note:(ここでまとめたデータの生データも貼ってある)’))n ((‘note:github.com/groonga/wikipedia-search/issues/2’))

まとめ1

* データが少ないならLIKEで十分
  * 1レコード数十バイトなら\n
    百万件はいける
* データが多いならLIKEはツライ

まとめ2

* データ多→pg_bigmかPGroonga
  * 2文字以下での全文検索がほとんど\n
    →pg_bigm
  * ストリーミングレプリケーション要\n
    →pg_bigm
  * ヒット件数が多い→PGroonga
  * レコードサイズが大きい→PGroonga
  * 更新が多い→PGroonga\n
    (('note:(インデックス作成が速いから)'))

参考情報

((‘tag:center’)) PGroongaでもn レプリケーションできる!

((‘tag:margin-top’)) pg_shardとPGroongaを使ったn レプリケーション対応のn 高速日本語全文検索可能なn PostgreSQLクラスターの作り方n ((‘note:www.clear-code.com/blog/2015/5/18.html’))