VCIを利用する場合の注意事項を説明します。
VCIの利用有無にかかわらず、結果の内容は変わりません。ただし、“ORDER BY”が指定されていない場合は、レコードの返却順については変わる可能性があります。
リソースの消費を制限するため、特定の時間帯や特定の業務(SQLアプリケーション)においてのみ本機能を利用する場合は、postgresql.confのパラメータ編集やSET文により“vci.enable”パラメータの有効化/無効化を行ってください。
オプティマイザヒント(pg_hint_plan)にVCIは指定できません。指定した場合、そのヒント句は無視されます。
オプティマイザヒント(pg_hint_plan)にVCI以外のプランを指定した場合でも、VCIが利用される場合があります。このため、ヒント句で問い合わせ計画を指定する場合は、SET文で“vci.enable”パラメータにoffを指定してください。
ストリーミングレプリケーションのスタンバイサーバでVCIを利用した検索を行うと、以下のメッセージが出力されることがあります。
"LOG: recovery has paused" "HINT: Execute pg_wal_replay_resume() to continue."
本メッセージは、VCIを利用した検索によりVCIに対するWALの適用が一時的に待機するために出力されます。
VCIを利用した検索を実行した場合でも、収集済み統計情報ビューであるpg_stat_all_indexesおよびpg_stat_user_indexesのidx_scan、idx_tup_read、idx_tup_fetch列の情報は更新されません。
現在は、パラレル集約の実行計画を、VCIを利用した実行計画に置き換えることはできません。このため、パーティションテーブルのある列にVCIを作成し、その列に対して集約(sum()など)すると、以下のいずれかのプランを選択します。対象のテーブルの状況に合わせて、設定パラメータを変えて使い分けてください。
VCIスキャン以外のスキャン方法を使用したパラレル集約のプラン
max_parallel_workers_per_gatherが1以上の場合に選択されます。
explain select sum(value) from test; QUERY PLAN -------------------------------------------------------------------------------------------------- Finalize Aggregate (cost=99906.30..99906.31 rows=1 width=8) -> Gather (cost=99906.08..99906.29 rows=2 width=8) Workers Planned: 2 -> Partial Aggregate (cost=98906.08..98906.09 rows=1 width=8) -> Parallel Append (cost=0.00..94739.83 rows=1666500 width=4) -> Parallel Seq Scan on test_1 (cost=0.00..43203.67 rows=833250 width=4) -> Parallel Seq Scan on test_2 (cost=0.00..43203.67 rows=833250 width=4)
このプランは、集約対象となる件数(検索条件にヒットする件数)が非常に多い場合には高速です。なぜなら、スキャンの性能ではなく集約を並列化するメリットが重要だからです。例えば、各パラレルワーカーはシーケンシャルスキャンしながら、スキャンしたレコードのほとんどを集約していきます。
VCIスキャンの結果を1多重で集約するプラン
max_parallel_workers_per_gatherを0に設定し、パラレル集約の実行計画を作成しないようにすることで選択されます。
explain select sum(value) from test; QUERY PLAN --------------------------------------------------------------------------------------------------- Aggregate (cost=145571.00..145571.01 rows=1 width=8) -> Append (cost=0.00..135572.00 rows=3999600 width=4) -> Custom Scan (VCI Scan) using test_1_id_value_idx on test_1 (cost=0.00..57787.00 rows=1999800 width=4) Allocated Workers: 2 -> Custom Scan (VCI Scan) using test_2_id_value_idx on test_2 (cost=0.00..57787.00 rows=1999800 width=4) Allocated Workers: 2
このプランは、集約対象となる件数がそれほど多くない場合や、レコードサイズに比べて集約対象の列のサイズが小さい場合には高速です。なぜなら、スキャン性能がより重要であるため、各パーティションのVCIスキャンの結果をより高速に集約できるからです。
アクセス対象のパーティションが1つの場合には、本来ならば下記のようなVCI集約のプランを使用できます。下記は、パーティション除去によって、1つのパーティションのみをスキャンする場合の例です。
explain select sum(value) from test where id < 1000001; QUERY PLAN ------------------------------------------------------------------------------------------------------- Custom Scan (VCI Aggregate) (cost=62786.50..62786.51 rows=1 width=8) Allocated Workers: 2 -> Custom Scan (VCI Scan) using test_1_id_value_idx on test_1 (cost=0.00..57787.00 rows=1999800 width=4) Filter: (id < 1000001)
しかし、現在のプランナは、テーブルがパーティショニングされていると、パラレル集約のプランを作成するため、VCI集約を選択しようとしません。そのため、このケースにおいてはmax_parallel_workers_per_gatherを0に設定して、強制的に、プランナがVCI集約を選択するようにしてください。