[Dd]enzow(ill)? with DB and Python

DBとか資格とかPythonとかの話をつらつらと

PostgreSQLで全文検索(PGroongaを試してみた:環境構築から簡単なINDEX試すまで)

前回はpg_bigmをつかってPostgreSQLで全文検索を行う方法を試しました。数年前から登場し、PostgreSQLの日本語全文検索ではpg_bigmと同じくらい耳にするPGroongaを試してみます。

PGroonga?

以下はドキュメントからの抜粋です。

PGroongaはPostgreSQLの拡張機能です。PGroongaはGroongaを使った新しいインデックスアクセスメソッドを提供します。 Groongaは組み込み可能な超高速全文検索エンジンです。GroongaはMySQLにも組み込めます。MroongaはGroongaベースのストレージエンジンです。Groongaはスタンドアローンの検索エンジンとしても使えます。 PostgreSQLはアルファベットと数値だけを使った言語の全文検索だけをサポートしています。これは、日本語や中国語などはサポートしていないということです。PGroongaをPostgreSQLにインストールすると全言語対応の超高速全文検索機能を使えるようになります! さらに、PGroongaはJSON内のすべてのテキスト値に対する全文検索もサポートしています。これは他にはない機能です。組み込みのPostgreSQLの機能でもJsQueryでもサポートしていません。

GroongaをPostgreSQLから利用できるようにする拡張のようです。

対象環境

今回は以下の環境で実施しました。

  • Ubuntu 16.04
  • PostgreSQL 9.6.5
  • PGroonga 2.0.1

Groonga

Groongaを使うので当然先にインストールしなければいけません。各プラットフォーム向けにパッケージがあるみたいですが、ソースからコンパイルしてみます。手順はこれです。

依存パッケージの準備

先に必要なパッケージを入れておきます。

sudo apt-get install -y -V  wget tar build-essential pkg-config zlib1g-dev libmsgpack-dev libzmq3-dev libevent-dev libmecab-dev liblz4-dev libzstd-dev

ソースの準備

Groongaのソースを準備します。

denzow@denzow-ubuntu:~/work/groonga$ mkdir -p ~/work/groonga/
denzow@denzow-ubuntu:~/work/groonga$ cd ~/work/groonga/
denzow@denzow-ubuntu:~/work/groonga$ wget https://packages.groonga.org/source/groonga/groonga-7.0.6.tar.gz
--2017-09-10 12:57:20--  https://packages.groonga.org/source/groonga/groonga-7.0.6.tar.gz
packages.groonga.org (packages.groonga.org) をDNSに問いあわせています... 133.18.25.129
packages.groonga.org (packages.groonga.org)|133.18.25.129|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 14558308 (14M) [application/x-gzip]
`groonga-7.0.6.tar.gz' に保存中

groonga-7.0.6.tar.gz                                              100%[============================================================================================================================================================>]  13.88M  3.29MB/s    in 4.3s

2017-09-10 12:57:25 (3.21 MB/s) - `groonga-7.0.6.tar.gz' へ保存完了 [14558308/14558308]

denzow@denzow-ubuntu:~/work/groonga$ tar xzf groonga-7.0.6.tar.gz
denzow@denzow-ubuntu:~/work/groonga$ cd groonga-7.0.6
denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$

ビルド

ビルドしていきます。インストール先だけ変更するので--prefixを指定しておきます。

denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ mkdir -p ~/groongaHome/groonga-7.0.6
denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ ./configure --prefix=$HOME/groongaHome/groonga-7.0.6
:

Tools:
  Sphinx:
  lemon:                 none
  Ruby:
  Cutter:

For packages:
  rsync path:            packages@packages.groonga.org:public
  Launchpad PGP key:
  GPG UID:               45499429

Now type 'make' to build groonga 7.0.6!

できたようなのでmake && make installします。

denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ make -j4
denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ make install

インストールできてるか試してみます。

denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ /home/denzow/groongaHome/groonga-7.0.6/bin/groonga --version
Groonga 7.0.6 [linux-gnu,x86_64,utf8,match-escalation-threshold=0,nfkc,mecab,msgpack,onigmo,zlib,lz4,zstd,epoll]

configure options: < '--prefix=/home/denzow/groongaHome/groonga-7.0.6'>

入ったようです。恐らくPATHやLD_LIBRARY_PATHは通さないといけないはずですので、.bashrcに追記しておきます。

denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ echo 'export PATH=$PATH:/home/denzow/groongaHome/groonga-7.0.6/bin/' >> ~/.bashrc
denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/denzow/groongaHome/groonga-7.0.6/lib/' >> ~/.bashrc

denzow@denzow-ubuntu:~/work/groonga/groonga-7.0.6$ . ~/.bashrc

PGroonga

ソースからビルドするのが好きなので、ドキュメントを参考にしながら試していきます。

依存パッケージの準備

WALを生成させるにはlibmsgpack-devが必要らしいので先に入れておきます。Groongaをいれているのであれば入ってそうですが。

denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ sudo apt-get install libmsgpack-dev

ソースの準備

ソースを持ってきて準備します。

denzow@denzow-ubuntu:~/work/pgroonga$ mkdir -p ~/work/pgroonga/
denzow@denzow-ubuntu:~/work/pgroonga$ cd ~/work/pgroonga/
denzow@denzow-ubuntu:~/work/pgroonga$ wget https://packages.groonga.org/source/pgroonga/pgroonga-2.0.1.tar.gz
--2017-09-10 12:50:24--  https://packages.groonga.org/source/pgroonga/pgroonga-2.0.1.tar.gz
packages.groonga.org (packages.groonga.org) をDNSに問いあわせています... 133.18.25.129
packages.groonga.org (packages.groonga.org)|133.18.25.129|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 264156 (258K) [application/x-gzip]
`pgroonga-2.0.1.tar.gz' に保存中

pgroonga-2.0.1.tar.gz                                             100%[============================================================================================================================================================>] 257.96K  --.-KB/s    in 0.1s

2017-09-10 12:50:24 (2.58 MB/s) - `pgroonga-2.0.1.tar.gz' へ保存完了 [264156/264156]

denzow@denzow-ubuntu:~/work/pgroonga$ tar xf pgroonga-2.0.1.tar.gz
denzow@denzow-ubuntu:~/work/pgroonga$ cd pgroonga-2.0.1
denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$

ビルド

HAVE_MSGPACK=1つきでビルドしてみます。

denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ make HAVE_MSGPACK=1
make -f pgroonga.mk all
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' に入ります
Package msgpack was not found in the pkg-config search path.
Perhaps you should add the directory containing `msgpack.pc'
to the PKG_CONFIG_PATH environment variable
No package 'msgpack' found
Package groonga was not found in the pkg-config search path.
Perhaps you should add the directory containing `groonga.pc'
to the PKG_CONFIG_PATH environment variable
No package 'groonga' found
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -Ivendor/xxHash -DPGRN_HAVE_MSGPACK -DPGRN_VERSION="\"2.0.1\"" -fPIC  -I. -I./ -I/home/denzow/posgreHome/pg965/include/postgresql/server -I/home/denzow/posgreHome/pg965/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/pgroonga.o src/pgroonga.c
In file included from src/pgroonga.c:5:0:
src/pgrn-command-escape-value.h:3:21: fatal error: groonga.h: そのようなファイルやディレクトリはありません
compilation terminated.
<ビルトイン>: ターゲット 'src/pgroonga.o' のレシピで失敗しました
make[1]: *** [src/pgroonga.o] エラー 1
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' から出ます
Makefile:2: ターゲット 'all' のレシピで失敗しました
make: *** [all] エラー 2

おや。失敗しました。No package 'msgpack' foundNo package 'groonga' foundが原因っぽいです。恐らくインストール先をいじっているからでしょう。マニュアルをよく見るとこの場合はPKG_CONFIG_PATH環境変数を使えと書いてありました。msgpack.pcとgroonga.pcが配置されている場所を追加して実行します。

denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ echo 'export PKG_CONFIG_PATH=$HOME/groongaHome/groonga-7.0.6/lib/pkgconfig/:$HOME/work/pgroonga/pgroonga-2.0.1/data/travis/pkgconfig/' >> ~/.bashrc
denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ . ~/.bashrc

denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ make HAVE_MSGPACK=1
make -f pgroonga.mk all
:
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' から出ます

denzow@denzow-ubuntu:~/work/pgroonga/pgroonga-2.0.1$ make install
make -f pgroonga.mk install
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' に入ります
/bin/mkdir -p '/home/denzow/posgreHome/pg965/lib/postgresql'
/bin/mkdir -p '/home/denzow/posgreHome/pg965/share/postgresql/extension'
/bin/mkdir -p '/home/denzow/posgreHome/pg965/share/postgresql/extension'
/usr/bin/install -c -m 755  pgroonga.so '/home/denzow/posgreHome/pg965/lib/postgresql/pgroonga.so'
/usr/bin/install -c -m 644 .//pgroonga.control '/home/denzow/posgreHome/pg965/share/postgresql/extension/'
/usr/bin/install -c -m 644 .//data/pgroonga--2.0.1.sql .//data/pgroonga--1.0.0--1.0.1.sql .//data/pgroonga--1.0.1--1.0.2.sql .//data/pgroonga--1.0.2--1.0.3.sql .//data/pgroonga--1.0.3--1.0.4.sql .//data/pgroonga--1.0.4--1.0.5.sql .//data/pgroonga--1.0.5--1.0.6.sql .//data/pgroonga--1.0.6--1.0.7.sql .//data/pgroonga--1.0.7--1.0.8.sql .//data/pgroonga--1.0.8--1.0.9.sql .//data/pgroonga--1.0.9--1.1.0.sql .//data/pgroonga--1.1.0--1.1.1.sql .//data/pgroonga--1.1.1--1.1.2.sql .//data/pgroonga--1.1.2--1.1.3.sql .//data/pgroonga--1.1.3--1.1.4.sql .//data/pgroonga--1.1.4--1.1.5.sql .//data/pgroonga--1.1.5--1.1.6.sql .//data/pgroonga--1.1.6--1.1.7.sql .//data/pgroonga--1.1.7--1.1.8.sql .//data/pgroonga--1.1.8--1.1.9.sql .//data/pgroonga--1.1.9--1.2.0.sql .//data/pgroonga--1.2.0--1.2.1.sql .//data/pgroonga--1.2.1--1.2.2.sql .//data/pgroonga--1.2.2--1.2.3.sql .//data/pgroonga--1.2.3--2.0.0.sql .//data/pgroonga--2.0.0--2.0.1.sql  '/home/denzow/posgreHome/pg965/share/postgresql/extension/'
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' から出ます
make -f pgroonga-check.mk install
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' に入ります
/bin/mkdir -p '/home/denzow/posgreHome/pg965/lib/postgresql'
/usr/bin/install -c -m 755  pgroonga_check.so '/home/denzow/posgreHome/pg965/lib/postgresql/pgroonga_check.so'
make[1]: ディレクトリ '/home/denzow/work/pgroonga/pgroonga-2.0.1' から出ます

インストールできたようです。

DBへのロード

インストールをみていると、とりあえずテストDBを作ってそこにロードしているので従います。

denzow@denzow-ubuntu:~$ createdb pgroonga_test
denzow@denzow-ubuntu:~$ psql pgroonga_test
psql (9.6.5)
Type "help" for help.

pgroonga_test=# CREATE EXTENSION pgroonga;
CREATE EXTENSION

サンプルの実行

早速、PGroongaを使ったINDEXを試してみます。手順はチュートリアルを参考にします。

pgroonga_test=# CREATE TABLE memos (
pgroonga_test(#   id integer,
pgroonga_test(#   content text
pgroonga_test(# );
CREATE TABLE
pgroonga_test=#
pgroonga_test=# CREATE INDEX pgroonga_content_index ON memos USING pgroonga (content);
CREATE INDEX
pgroonga_test=# INSERT INTO memos VALUES (1, 'PostgreSQLはリレーショナル・データベース管理システムです。');
INSERT 0 1
pgroonga_test=# INSERT INTO memos VALUES (2, 'Groongaは日本語対応の高速な全文検索エンジンです。');
INSERT 0 1
pgroonga_test=# INSERT INTO memos VALUES (3, 'PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。');
INSERT 0 1
pgroonga_test=# INSERT INTO memos VALUES (4, 'groongaコマンドがあります。');
INSERT 0 1
pgroonga_test=#
pgroonga_test=# SET enable_seqscan = off;
SET
pgroonga_test=#
pgroonga_test=# SELECT * FROM memos WHERE content &@ '全文検索';
 id |                      content
----+---------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
(1 row)

pgroonga_test=# explain analyze SELECT * FROM memos WHERE content &@ '全文検索';
                                                           QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on memos  (cost=0.16..10.85 rows=635 width=36) (actual time=0.424..0.425 rows=1 loops=1)
   Recheck Cond: (content &@ '全文検索'::text)
   Heap Blocks: exact=1
   ->  Bitmap Index Scan on pgroonga_content_index  (cost=0.00..0.00 rows=13 width=0) (actual time=0.413..0.413 rows=1 loops=1)
         Index Cond: (content &@ '全文検索'::text)
 Planning time: 0.137 ms
 Execution time: 0.641 ms
(7 rows)

ちゃんとBitmap Index Scan on pgroonga_content_indexになっているので構築できているようです。