FOSS4G Advent Calendar 2017 の 12/10 の記事です。
勉強もかねて、勇気をだして参加してみたものの、本記事はうまく行かなかったという内容になりました。ご了承願います… (..)_
PostgreSQL 9.6 から、パラレルクエリという機能が使えるようになったようです。通常は、ひとつの CPU のみのところ、複数の CPU を使用するので速いと思われます。
PostgreSQL 9.6.6, PostGIS 2.3.2 で試しました。
パラレルクエリの有効化
初期設定では、パラレルクエリを使わない設定になっているので、有効化します。postgresql.conf という設定ファイルの
max_parallel_workers_per_gather = 0
の値を1以上にします。手元のマシンはCPUのプロセッサ数が8こあるので、8にしたいと思います。
postresql.conf を書き換えたくない場合は、
SET max_parallel_workers_per_gather = 8;
の SQL を実行するだけでも大丈夫です。
さっそく使ってみる
COUNT
まずは、普通の集計関数を使ってみます。
SELECT COUNT(*) FROM table_a;
count
----------
34620352
(1 row)
3.5sec -> 1.0secs
1/3以下の時間に短縮されました
ST_Area
次に面積を計測する ST_Area を使ってみます。
SELECT ST_Area(geom) AS area FROM porigon_table_a;
01:27 minutes -> 01:27 minutes
あれ? 変わらないですね。
実行したい SQL の前に EXPLAIN をつけると、問い合わせ計画というものが見られるので、これで確認してみます。
EXPLAIN SELECT ST_Area(geom) FROM porigon_table_a;
QUERY PLAN
-------------------------------------------------------------
Seq Scan on porigon_table_a (cost=0.00..355507.09 rows=2264031 width=8)
これは、パラレル使用の設定にしているのに、パラレルが使われていないようです。
ちなみに、ひとつ目のクエリでパラレルが使われた例の場合の EXPLAIN は以下のようになります。
QUERY PLAN
-------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=1686681.79..1686681.80 rows=1 width=8)
-> Gather (cost=1686681.06..1686681.77 rows=7 width=8)
Workers Planned: 7
-> Partial Aggregate (cost=1685681.06..1685681.07 rows=1 width=8)
-> Parallel Seq Scan on table_a (cost=0.00..1673316.65 rows=4945765 width=0)
パラレルが使われるかどうかは、プランナーがコストを推定して判断するらしいです。とりあえず使ってみて欲しい場合は、以下のようにします。
SET parallel_setup_cost = 0
SET parallel_tuple_cost = 0
それでもう一度実行してみると…、パラレルは使われましたが、処理時間は変わりませんでした。
EXPLAIN SELECT ST_Area(geom) FROM porigon_table_a;
QUERY PLAN
-------------------------------------------------------------------------------------------------
Gather (cost=0.00..337097.04 rows=2281164 width=8)"
Workers Planned: 6"
-> Parallel Seq Scan on porigon_table_a (cost=0.00..289572.79 rows=380194 width=8)"
SELECT ST_Area(geom) FROM porigon_table_a;
01:27 ms -> 01:27 ms
また、ST_Intersects も試しましたが、同様に変わらなかったです。
結論
このバージョン(PostgreSQL 9.6.6, PostGIS 2.3.2)では パラレルクエリはPostGIS に適さないみたいです。
[ポールラムジーさんが PostgreSQL 10、PostGIS 2.4 で空間関数のコストを調整しながらやっているので]
(http://blog.cleverelephant.ca/2017/10/parallel-postgis-2.html)、今度は 10 で試したいと思います(昨日リリースなので今回はちょっと入れ替えが間に合いませんでした、すみません)。