【PostgreSQL】enable_seqscan について検証してみた (その1)

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は、PostgreSQL の enable_seqscan について検証を行なってみました。(※以下の内容は CentOS 7.6/PostgreSQL 11.1 にて検証しています。)

■はじめに

今回は enable_seqscan についてのお話です。

PostgreSQL は、基本的に実行計画を自動で作成した上でクエリを実行してくれますが、設定を変更することで特定の実行プランの利用可否 (例: Hash Join は使わない、等) を指定することが可能です。

上記設定は、パラメータ “enable_*” で実行プラン毎に on/off を指定するのですが、一部のパラメータ (enable_material/enable_nestloop/enable_seqscan/enable_sort) には “完全に無効にすることはできない (It is impossible to suppress ~ entirely,)” と記載されています。

例えば、enable_seqscan のドキュメントの記載は以下の様になっています。

enable_seqscan (boolean)

Enables or disables the query planner's use of sequential scan plan types. It is impossible to suppress sequential scans entirely, but turning this variable off discourages the planner from using one if there are other methods available. The default is on.

この “完全に無効にはできない” という部分が少し気になったので、実際に enable_seqscan の設定を変更して検証してみました。

■検証

それではさっそく、検証してみます。

まずは、以下の様なテスト用のテーブルを作成します。

postgres=# CREATE TABLE hoge (a int);
CREATE TABLE
postgres=# 
postgres=# INSERT INTO hoge VALUES (1);
INSERT 0 1
postgres=# 
postgres=# ANALYZE hoge;
ANALYZE
postgres=# 
postgres=# SELECT * FROM hoge;
 a 
---
 1
(1 row)

postgres=# 

enable_seqscan のデフォルト値は “on” (シーケンシャルスキャンが有効) であるため、まずはデフォルト設定のまま EXPLAIN ANALYZE 文にてクエリ “SELECT * FROM hoge” を実行する際の実行プランを表示してみます。

postgres=# SHOW enable_seqscan;
 enable_seqscan 
----------------
 on
(1 row)

postgres=# 
postgres=# EXPLAIN ANALYZE SELECT * FROM hoge;
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Seq Scan on hoge  (cost=0.00..1.01 rows=1 width=4) (actual time=0.012..0.013 rows=1 loops=1)
 Planning Time: 0.079 ms
 Execution Time: 0.029 ms
(3 rows)

postgres=# 

すると、”Seq Scan on hoge” と出力されており、シーケンシャルスキャンが利用されていることが確認できます。

次に enable_seqscan の値を “off” (シーケンシャルスキャン無効) に設定して、同様に EXPLAIN ANALYZE 文を実行してみます。

postgres=# SET enable_seqscan TO 'off';
SET
postgres=# 
postgres=# SHOW enable_seqscan;
 enable_seqscan 
----------------
 off
(1 row)

postgres=# 
postgres=# EXPLAIN ANALYZE SELECT * FROM hoge;
                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Seq Scan on hoge  (cost=10000000000.00..10000000001.01 rows=1 width=4) (actual time=0.016..0.017 rows=1 loops=1)
 Planning Time: 0.063 ms
 Execution Time: 0.033 ms
(3 rows)

postgres=# 

すると、enable_seqscan = off であっても、”Seq Scan on hoge” と出力されており、シーケンシャルスキャンが利用されていることが確認できます。

確かに、”シーケンシャルスキャンを完全に無効にする” ことはできないようです。

また、enable_seqscan が on の場合と off の場合の EXPLAIN ANALYZE の結果を見ると、同じテーブルに対する同じクエリであるにも関わらず、”cost” の値が大きく違っていることが確認できます。

念のため、ANALYZE を実行してから再度 EXPLAIN ANALYZE を実行しても、cost の値は変化しておらず、統計情報の問題では無いようです。

postgres=# ANALYZE hoge;
ANALYZE
postgres=# 
postgres=# SHOW enable_seqscan;
 enable_seqscan 
----------------
 off
(1 row)

postgres=# 
postgres=# EXPLAIN ANALYZE SELECT * FROM hoge;
                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Seq Scan on hoge  (cost=10000000000.00..10000000001.01 rows=1 width=4) (actual time=0.008..0.009 rows=1 loops=1)
 Planning Time: 0.084 ms
 Execution Time: 0.026 ms
(3 rows)

このあたりの処理 (enable_seqscan の値を変えると、cost の値が変わる) に “完全に無効にはできない” という部分の仕組みが隠されているよう気ながします。

■最後に

今回は、PostgreSQL のドキュメントに記載されている “enable_seqscan を off に設定してもシーケンシャルスキャンを完全に無効にすることはできない” という内容を実際に検証してみました。

結果として、ドキュメントに記載されている通りシーケンシャルスキャンを完全に無効にすることはできませんでした。また、実行計画を作成する際の “cost” に “完全に無効にできない” とう部分の仕組みがあるように見受けられます。

次回は、enable_seqscan を off に設定した際の処理をもう少し深堀りしてみようと思います。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

1人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です