PostgreSQLアンカンファレンス@東京(2015/5/30)でPostgreSQLの日本語全文検索まわりについて紹介しようかとたくらんでいます。しかし、現時点(2015-05-25)でキャンセル待ちで、当日参加できないかもしれないので紹介しようと用意している内容をここにまとめます。
内容
この資料の目的は、PostgreSQLで使える次の3つの方法の特性を紹介し、ユーザーが適切な方法を選択するための材料を提供することです。
LIKE
LIKE
のメリット・デメリットは次の通りです。
-
メリット
-
- 標準で使える
- インデックス作成不要(= データ更新が遅くならない)
- データが少なければ十分速い
-
デメリット
-
- データ量に比例して遅くなる
ユーザーがLIKE
を使うかどうかの判断基準は「十分速いかどうか」(= 「データが少ないかどうか」)です。では、どのくらいなら「十分速い」のでしょうか。
「十分速い」かどうかは「検索対象のデータでの計測結果」と「要件」で判断できます。どちらもケースバイケースですが、参考情報としての計測結果なら示すことができます。
参考情報としてpg_bigmでいろんなデータを日本語検索してみよう!のLIKE
の結果を使ってみましょう。この記事では次の3つのデータを検索しています。
- 青空文庫の書籍一覧データ
- 住所データ
- 日本版Wikipediaのタイトル一覧データ
それぞれみていきましょう。
まずは「青空文庫の書籍一覧データ」です。
このデータの特性と検索速度は次の通りです。
件数 | 1レコードあたりのバイト数 | 検索速度 |
---|---|---|
11,818件 | 17バイト | 6.673ms |
6msで結果が返ってくるのであれば多くの要件で「十分速い」と言えるでしょう。つまり、このデータでは日本語全文検索の方法としてLIKE
はアリということです。
次のデータは「住所データ」です。
このデータの特性と検索速度は次の通りです。
件数 | 1レコードあたりのバイト数 | 検索速度 |
---|---|---|
147,769件 | 14バイト | 70.684ms |
70msで結果が返ってくるのであれば多くの要件で「十分速い」と言えるでしょう。つまり、このデータでも日本語全文検索の方法としてLIKE
はアリということです。
最後のデータは「日本版Wikipediaのタイトル一覧データ」です。
このデータの特性と検索速度は次の通りです。
件数 | 1レコードあたりのバイト数 | 検索速度 |
---|---|---|
2,461,588件 | 20バイト | 943.450ms |
1秒くらいで結果が返ってくるのでは、「十分速い」というのは要件次第でしょう。つまり、この規模のデータでは日本語全文検索の方法としてLIKE
は使えるかもしれないし使えないかもしれない、といったところです。
これまでの結果をまとめると次の通りです。LIKE
で十分かどうかを判断する場合は、実際のデータの傾向と検索時間を材料として検討します。
件数 | 1レコードあたりのバイト数 | 検索速度 |
---|---|---|
11,818件 | 17バイト | 6.673ms |
147,769件 | 14バイト | 70.684ms |
2,461,588件 | 20バイト | 943.450ms |
では、LIKE
では十分速くない場合はどうしたらよいでしょうか。次のどちらかの方法を選びます。
- pg_bigm
- PGroonga
pg_bigm
pg_bigmのメリット・デメリットは次の通りです。
-
メリット
-
- データ量が多くても高速
- ストリーミングレプリケーションを使える
-
デメリット
-
- 別途インストールしないといけない
- インデックス作成が遅い(= データ更新が遅くなる)
- ヒット数に比例して遅くなる
pg_bigmはデータ量が多くても高速ですが、ヒット数が多いほど遅くなる特性があります。pg_bigmが十分速いかどうかを判断するためにも、LIKE
と同様に「検索対象のデータでの計測結果」と「要件」が必要です。ただし、LIKE
とは注目するポイントが異なります。
それでは、検索結果例を見ながら注目するポイントを確認しましょう。なお、ここで紹介する検索結果例はPGroongaとpg_bigmのベンチマーク結果 · Issue #2 · groonga/wikipedia-searchにあります。手順もまとまっているので誰でも追試することができます。 ここで使うデータは日本語版Wikipediaの本文です。このデータの特性は次の通りです。
件数 | 1レコードあたりのバイト数 |
---|---|
1,846,514件 | 3777バイト |
注目するポイントの1つ目はインデックス作成時間です。元データのロード時間とインデックス作成時間は次の通りです。
元データのロード時間 | インデックス作成時間 |
---|---|
16分31秒 | 5時間56分15秒 |
約16分でロードできるデータのインデックス作成に約6時間かかるのは十分速いでしょうか。それとも遅いでしょうか。要件と照らしあわせて検討します。
なお、この時間はインデックス全体を1から作成する時間です。常に少量ずつ更新するという要件であればこの時間はあまり関係ありません。そのような要件の場合は、少量のデータの更新が滞らない(更新処理が溜まっていかない)くらいの速度がでていれば十分速いと判断できます。
注目するポイントの2つ目はヒット数と検索時間の関係です。
検索語 | ヒット数 | 検索時間 |
---|---|---|
「PostgreSQL」または「MySQL」 | 361 | 0.107s |
データベース | 17168 | 1.224s |
テレビアニメ | 22885 | 2.472s |
日本 | 625792 | 0.556s |
pg_bigmはヒット数が多くなるほど遅くなります。数百件ヒットのときは0.1秒ですが、1万7千件のときは1秒ちょい、2万2千件のときは約2.5秒となりました。なお、このデータではヒット数が増えるほど遅くなる傾向がよりわかりやすいデータになっています。というのは、このデータは1レコードあたりのデータが大きいからです。pg_bigmは1レコードあたりのデータが大きいと遅くなりやすい特性があります。
なお、検索語が2文字以下の場合はヒット数が多くても遅くなりにくいという特性があります。例では62万件ヒットしても0.5秒で結果を返しています。
このような特性があるpg_bigmなので、データによっては遅いと判断する場面も十分速いと判断する場面もあるでしょう。
PGroonga
LIKE
では遅い場合、pg_bigm以外の選択肢はPGroongaです。
PGroongaのメリット・デメリットは次の通りです。
-
メリット
-
- インデックス作成が速い
- データ量が多くても高速
- ヒット数が多くても高速
-
デメリット
-
- 別途インストールしないといけない
- ストリーミングレプリケーション非対応
- 使用ディスクサイズが多い
PGroongaはデータ量が多くてもヒット数が多くても速度が落ちにくく、インデックス作成も高速ですが、PostgreSQLとの連携度合いはpg_bigmほどではありません。たとえば、pg_bigmはPostgreSQL標準のストリーミングレプリケーション機能を使えますが、PGroongaは使えません。これはPostgreSQL側が連携する機能を提供していないことが原因です。今後連携できる機能が提供される見込みですが、現時点で連携できないことは事実です。
PGroongaを選ぶかどうかの基準は他の方法では遅いケースがPGroongaだと速いかどうかです。そのためには同じデータでpg_bigmと比較する必要があります。
それでは、pg_bigmと同じデータを使った場合のPGroongaの速度を確認しましょう。
まずはインデックス作成時間です。
元データのロード時間 | 16分31秒 |
---|---|
PGroongaのインデックス作成時間 | 25分37秒 |
pg_bigmのインデックス作成時間 | 5時間56分15秒 |
参照しやすいようにpg_bigmのインデックス作成時間も再掲しています。
PGroongaは元データのロード時間の2倍いかないくらいの時間でインデックスを作成しています。pg_bigmと比べると1/14の時間でインデックスを構築できています。
ただし、インデックスのために使用するディスクサイズは大きいです。
元データロード直後のデータベースサイズ | 4.0GiB |
---|---|
PGroongaの使用ディスクサイズ | 14.0GiB | pg_bigmの使用ディスクサイズ | 3.6GiB |
ディスクサイズが小さい環境で動かす場合は問題になるかもしれません。
次は検索時間を確認しましょう。
検索語 | ヒット数 | PGroongaの検索時間 | pg_bigmの検索時間 |
---|---|---|---|
「PostgreSQL」または「MySQL」 | 368 | 0.030s | 0.107s |
データベース | 17172 | 0.121s | 1.224s |
テレビアニメ | 22885 | 0.179s | 2.472s |
日本 | 625792 | 0.646s | 0.556s |
PGroongaはpg_bigmほどヒット数の多さに影響をうけていません。62万件ヒットする場合でも0.6秒ちょいで結果を返しています。PGroongaは全体的に高速ですが、検索語が2文字以下の場合はpg_bigmの方が高速です。
PostgreSQLとの連携度合いよりも性能が大事な要件な場合で、pg_bigmでは性能が落ちやすい規模のデータではPGroongaが選択肢になるでしょう。
まとめ
PostgreSQLで日本語全文検索の方法として次の3つの方法を紹介しました。
LIKE
- pg_bigm
- PGroonga
データが少ないならLIKE
で十分です。要件次第ですが、1レコード数十バイトの小さなデータなら百万件くらいまでいけるかもしれません。
データが多いならpg_bigmかPGroongaを選びます。
次のような場合はpg_bigmがよいでしょう。
- 2文字以下での検索がほとんど
- 1レコードあたりのデータが小さい
- ヒット数が多くなることがほとんどない
- ストリーミングレプリケーションを使いたい
pg_bigmで次のような問題があるならPGroongaがよいでしょう。
- 1レコードあたりのデータが大きい
- ヒット数が多くなるケースを考慮しないといけない
- 更新が多くてインデックス更新速度がネックになる
ちなみに、PGroongaでもレプリケーションをする方法はあります。興味のある方はpg_shardとPGroongaを使ったレプリケーション対応の高速日本語全文検索可能なPostgreSQLクラスターの作り方を参考にしてください。
最後に、PostgreSQLの日本語全文検索に興味のある方にお願いです。この説明の中のpg_bigmとPGroongaの性能確認で参照したベンチマークをあなたの環境でも動かして結果を教えてもらえないでしょうか?同じ傾向があるか確認したいのです。ベンチマークの実行方法や必要な環境などの詳細は協力者募集:PGroongaとpg_bigmのベンチマークを実行を参照してください。