Postgresプランナの統計情報
ベータ版
6月15日より、LakebaseはGCPでベータとして利用可能です。サポートされているリージョンについては、「リージョンの可用性」を参照してください。
Postgresクエリープランナーは、プランナースタティスティクスを使用して、クエリーの各ステップが返す行数を見積もり、実行プランを選択します。このページでは、Postgresがプランナースタティスティクスを自動的に生成するタイミング、スタティスティクスが不足しているテーブルを見つける方法、テーブルの生成タイミングを変更する方法について説明します。Lakebaseがコンピュートの再起動とスケール・ツー・ゼロ全体でスタティスティクスを保持する方法については、スタティスティクスの収集を参照してください。
ANALYZEはいつテーブルでランしますか?
オートバキュームは、十分な行が変更された後にテーブルで ANALYZE を実行することにより、プランナー統計を自動的に生成します。テーブルは、前回の分析以降に挿入、更新、または削除された行数が次の値を超えたときに分析されます。
autovacuum_analyze_threshold + autovacuum_analyze_scale_factor × number of rows in the table
default設定(autovacuum_analyze_threshold = 50 と autovacuum_analyze_scale_factor = 0.1)では、新しいテーブルは 50 行を超えて挿入、更新、削除された後に解析され、既存のテーブルは 50 行に加えて行の 10% が変更された後に解析されます。その結果、1 回の読み込みで 50 行以下のデータしか保持せず、その後変更されないテーブルは、autovacuum によって解析されることはありません。プランナーの統計情報がない場合、プランナーはdefaultの推定値に依存するため、そのテーブルがより大きなテーブルと結合されたときに非効率的なクエリープランが作成される可能性があります。
Databricksでは、初期データの読み込み後に新しいテーブルで、また50行以下のテーブル(defaultの自動分析threshold)で ANALYZE を実行することをお勧めします。これにより、テーブルに対するクエリーを実行する前に、正確なプランナー統計を保持できます。
パーティション分割されたテーブルの分析
自動バキュームは、パーティション化されたテーブルの各パーティションを、そのパーティション内の行が変更されるにつれて分析しますが、パーティション化されたテーブル自体 (親) を分析することはありません。親の統計はテーブル全体を記述するものであり、親で ANALYZE をランしたときにのみ生成されます。これらがないと、パーティション化されたテーブルを参照するクエリーで非効率なプランが取得される可能性があります。最初にデータをロードした後、およびパーティション間でのデータの分散が大幅に変更されるたびに、親で ANALYZE をランします。
ANALYZE my_schema.my_partitioned_table;
親で ANALYZE を実行すると、Postgres はすべてのパーティションから行をサンプリングして親の統計を構築します。defaultでは、各パーティションも分析され、パーティションの統計が更新されますが、大規模なテーブルでは時間がかかる場合があります。
Postgres 18以上では、ANALYZE ONLY を使用して、各パーティションを分析せずに親の統計を更新します。Postgresは引き続きすべてのパーティションから行をサンプリングし、autovacuumは行の変更に応じてパーティションの分析を継続します。
ANALYZE ONLY my_schema.my_partitioned_table;
Postgres 16および17では、パーティションテーブルに対するANALYZEは常にすべてのパーティションを分析します。どのバージョンでも、1つのパーティションの統計を更新するには、そのパーティションでANALYZEをランを実行します。
プランナー統計のないテーブルを検索する
プランナー統計のないテーブルを探すには、 pg_stats ビューに行のないテーブルを探します。プランナー統計は永続的に保存されるため、累積統計がResetされた後でもこのチェックは信頼できます。クエリーは、システムスキーマ、および Lakebase が Data API と同期テーブルで内部的に使用するスキーマを除外します。
SELECT t.schemaname, t.tablename
FROM pg_tables t
WHERE t.schemaname NOT IN ('pg_catalog', 'information_schema', '__db_system', 'pgrst')
AND t.schemaname NOT LIKE '\_\_db\_user\_%'
AND NOT EXISTS (
SELECT 1 FROM pg_stats s
WHERE s.schemaname = t.schemaname AND s.tablename = t.tablename
)
ORDER BY 1, 2;
databricks_superuserロールのメンバーとして、またはテーブル所有者としてクエリーをランします。pg_statsビューには、現在のロールが読み取れる列の統計のみが表示されます。行レベルセキュリティが有効なテーブルについては、ロールが行レベルセキュリティをバイパスできない限り、統計情報も非表示になります。現在のロールでは読み取れないテーブル、または行レベルセキュリティが有効なテーブルは、統計情報が存在していても結果に表示されることがあります。
ANALYZEは空のテーブルの統計を生成しないため、データが含まれていたことのないテーブルも結果に表示されます。データを含み、クエリーで使用されるテーブルに注目します。
クエリーによって返されるテーブルのプランナー統計を生成するには、ANALYZEをランします:
ANALYZE my_schema.my_table;
現在のデータベース内のすべてのテーブルを分析するには、テーブル名を指定せずに ANALYZE をランします。
テーブルの自動バキューム設定をカスタマイズする
defaultのthresholdに対してテーブルの変更頻度が低すぎる場合は、そのテーブルの分析thresholdを下げることができます。たとえば、サイズに関係なく 10 行以上変更された後に小さな参照テーブルを分析するには、次のようにします。
ALTER TABLE my_schema.my_table SET (
autovacuum_analyze_threshold = 10,
autovacuum_analyze_scale_factor = 0
);
テーブルのカスタム設定を表示するには、pg_class.reloptionsをクエリーします。
SELECT relname, reloptions
FROM pg_class
WHERE oid = 'my_schema.my_table'::regclass;
defaultの動作を復元するには、設定をリセットします:
ALTER TABLE my_schema.my_table RESET (
autovacuum_analyze_threshold,
autovacuum_analyze_scale_factor
);
低いthresholdであっても、ロードされた行数がthresholdを超えず、その後にテーブルが変更されない場合、autovacuum はテーブルを解析しません。静的テーブルの場合、データのロード後に ANALYZE をランします。
情報については、Postgresのドキュメントを参照してください: