メインコンテンツまでスキップ

Postgresプランナの統計情報

Postgresクエリープランナーは、プランナースタティスティクスを使用して、クエリーの各ステップが返す行数を見積もり、実行プランを選択します。このページでは、Postgresがプランナースタティスティクスを自動的に生成するタイミング、スタティスティクスが不足しているテーブルを見つける方法、テーブルの生成タイミングを変更する方法について説明します。Lakebaseがコンピュートの再起動とスケール・ツー・ゼロ全体でスタティスティクスを保持する方法については、スタティスティクスの収集を参照してください。

ANALYZEはいつテーブルでランしますか?​

オートバキュームは、十分な行が変更された後にテーブルで ANALYZE を実行することにより、プランナー統計を自動的に生成します。テーブルは、前回の分析以降に挿入、更新、または削除された行数が次の値を超えたときに分析されます。

Text
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 をランします。

SQL
ANALYZE my_schema.my_partitioned_table;

親で ANALYZE を実行すると、Postgres はすべてのパーティションから行をサンプリングして親の統計を構築します。defaultでは、各パーティションも分析され、パーティションの統計が更新されますが、大規模なテーブルでは時間がかかる場合があります。

Postgres 18以上では、ANALYZE ONLY を使用して、各パーティションを分析せずに親の統計を更新します。Postgresは引き続きすべてのパーティションから行をサンプリングし、autovacuumは行の変更に応じてパーティションの分析を継続します。

SQL
ANALYZE ONLY my_schema.my_partitioned_table;

Postgres 16および17では、パーティションテーブルに対するANALYZEは常にすべてのパーティションを分析します。どのバージョンでも、1つのパーティションの統計を更新するには、そのパーティションでANALYZEをランを実行します。

プランナー統計のないテーブルを検索する​

プランナー統計のないテーブルを探すには、 pg_stats ビューに行のないテーブルを探します。プランナー統計は永続的に保存されるため、累積統計がResetされた後でもこのチェックは信頼できます。クエリーは、システムスキーマ、および Lakebase が Data API と同期テーブルで内部的に使用するスキーマを除外します。

SQL
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をランします:

SQL
ANALYZE my_schema.my_table;

現在のデータベース内のすべてのテーブルを分析するには、テーブル名を指定せずに ANALYZE をランします。

テーブルの自動バキューム設定をカスタマイズする​

defaultのthresholdに対してテーブルの変更頻度が低すぎる場合は、そのテーブルの分析thresholdを下げることができます。たとえば、サイズに関係なく 10 行以上変更された後に小さな参照テーブルを分析するには、次のようにします。

SQL
ALTER TABLE my_schema.my_table SET (
autovacuum_analyze_threshold = 10,
autovacuum_analyze_scale_factor = 0
);

テーブルのカスタム設定を表示するには、pg_class.reloptionsをクエリーします。

SQL
SELECT relname, reloptions
FROM pg_class
WHERE oid = 'my_schema.my_table'::regclass;

defaultの動作を復元するには、設定をリセットします:

SQL
ALTER TABLE my_schema.my_table RESET (
autovacuum_analyze_threshold,
autovacuum_analyze_scale_factor
);

低いthresholdであっても、ロードされた行数がthresholdを超えず、その後にテーブルが変更されない場合、autovacuum はテーブルを解析しません。静的テーブルの場合、データのロード後に ANALYZE をランします。

情報については、Postgresのドキュメントを参照してください: