Amazon Web Services ブログ

Aurora DSQL での Auto Analyze:マルチリージョンデータベースにおけるマネージドオプティマイザー統計

本記事は 2026/02/04に投稿された Auto Analyze in Aurora DSQL: Managed optimizer statistics in a multi-Region database を翻訳した記事です。

Amazon Aurora DSQL および他の最新のリレーショナルデータベースシステムにおいて、正確な統計情報はクエリプランにおける最も重要な要因の一つです。悪いクエリプランを良いクエリプランの代わりに誤って選択してしまうと、100倍の性能低下を引き起こす可能性があります。プランのリグレッションが発生するリスクを最小化するために、最新の統計情報が重要です。この投稿では、DSQL オプティマイザー統計を自動的に計算する確率的かつ事実上ステートレスな手法である Aurora DSQL Auto Analyze について解説します。PostgreSQL に精通しているユーザーは、autovacuum analyze との類似性を理解していただけるでしょう。

クエリパフォーマンスにおける統計情報の重要性

統計情報がクエリパフォーマンスに与える影響を説明するために、オプティマイザーがフルテーブルスキャンまたはインデックススキャンを使用してデータにアクセスするかを選択できる基本的な例を見てみましょう。統計情報の効果を説明するために、内部パラメータを使用してAuto Analyzeを無効にしました。お客様にとって、Auto Analyze は常に有効になっており、無効にするオプションはありません。

まず、int 型の列 A とtext 型の列 B を持つテーブルを生成します。また、列 A にインデックスを作成します。次に、このテーブルに 600,000 行を挿入します。この例では、列Aに注目します。300,000 行は0から299,999までのA値を含みます。残りの 300,000 行はA値が42です。

create table mytable (A int, B text); 
create index async mytableidx on mytable(A); 

SELECT 'INSERT INTO mytable SELECT generate_series(3000 * ' || i-1 || ', 3000 * ' || i || ' - 1), ''AWS Aurora DSQL is great'';' FROM generate_series(1, 100) i; 
\gexec 

SELECT 'INSERT INTO mytable SELECT 42, ''AWS Aurora DSQL is great'' FROM generate_series(1, 3000);' FROM generate_series(1, 100); 
\gexec

以下のクエリを使用して、A値が42の行が 300,001 行あることを確認します。したがって、A値が42の行は全体の半分以上を占めています。

SELECT count(*) FROM mytable GROUP BY GROUPING SETS (A = 42);
count
--------
299999
300001
(2 rows)

以下のコマンドを実行して、A値が42の全ての行を選択する場合に、オプティマイザーがどのプランを選択するかを観察してみましょう。

EXPLAIN ANALYZE SELECT * FROM mytable WHERE A = 42; 

QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------ 
 Index Scan using mytableidx on mytable  (cost=23193.32..34868.97 rows=92373 width=32) (actual time=15.926..5217.368 rows=300001 loops=1)
   Index Cond: (a = 42)
   -> Storage Scan on mytableidx (cost=23193.32..34868.97 rows=92373 width=32) (actual rows=300001 loops=1)
       -> B-Tree Scan on mytableidx (cost=23193.32..34868.97 rows=92373 width=32) (actual rows=300001 loops=1)
           Index Cond: (a = 42)
   -> Storage Lookup on mytable (cost=23193.32..34868.97 rows=92373 width=32) (actual rows=300001 loops=1)
       Projections: a, b
       -> B-Tree Lookup on mytable (cost=23193.32..34868.97 rows=92373 width=32) (actual rows=300001 loops=1)
 Planning Time: 3.367 ms
 Execution Time: 5228.314 ms
(10 rows)

選択されたプランにはインデックススキャンが含まれていることがわかります。A = 42が半数を占めることから、明らかにインデックスからの間接参照のコストを避けて、フルテーブルスキャンを選択することが期待されます。

オプティマイザーが最適なプランを見つけるのを助けるために、テーブルでANALYZEを実行します。

ANALYZE mytable;

今度は選択されたプランにフルテーブルスキャンが含まれています。クエリは半分以下の時間で完了するようになりました。

EXPLAIN ANALYZE 
SELECT * 
FROM mytable 
WHERE A = 42;

QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
 Full Scan (btree-table) on mytable  (cost=74756.80..87915.45 rows=296975 width=32) (actual time=1.179..1977.851 rows=300001 loops=1)
   -> Storage Scan on mytable (cost=74756.80..87915.45 rows=296975 width=32) (actual rows=300001 loops=1)
       Projections: a, b
       Filters: (a = 42)
       Rows Filtered: 299999
       -> B-Tree Scan on mytable (cost=74756.80..87915.45 rows=597254 width=32) (actual rows=600000 loops=1)
 Planning Time: 5.055 ms
 Execution Time: 1989.230 ms
(8 rows)

Aurora DSQL クラスターでこの例を再現すると、手動で analyze を実行する前でも、フルテーブルスキャンを使用する高速なクエリプランが得られることがわかります。Auto Analyze がバックグラウンドで自動的に統計情報を計算し、このパフォーマンス向上を提供してくれます。

Aurora DSQL における Auto Analyze

このセクションでは、まず PostgreSQL の autovacuuming について再確認します。次に、Aurora DSQL がマルチAWSリージョン環境において、事実上無制限のスケールで2つの構成要素を通じて PostgreSQL の動作を模倣する方法を説明します。

PostgreSQL では、ANALYZEは autovacuum デーモン (AUTOVACUUM) を通じて自動的にトリガーされます。これはテーブルの変更を継続的に監視し、事前定義された閾値に達した時(通常はテーブルの行の 10% が挿入、更新、または削除された後)に統計情報を更新します。詳細については、autovacuumデーモンのPostgreSQL ドキュメントを参照してください。

Aurora DSQL において、Auto Analyze 機能は PostgreSQL の autovacuum による ANALYZE 処理プロセスに相当し、クエリプランニングに不可欠なテーブル統計情報を自動的に維持します。PostgreSQL の決定論的な閾値ベースのアプローチとは異なり、DSQL は 2 つの主要な構成要素に基づいたマルチリージョン対応のソリューションを実装しています:

  • 確率的トリガーがトリガーメカニズムとして機能します。テーブルの変更を監視・追跡する代わりに、各トランザクションは、テーブルサイズに対して変更する行数に基づいて ANALYZE をトリガーする確率を計算します。この確率的アプローチにより、セッション間の調整の必要性がなくなり、テーブルの進化に応じて統計情報が更新されることを保証します。
  • サンプリングベースの analyze 手法が実際の統計計算を処理します。トリガーされると、ANALYZE はサンプリング技術を使用して、大規模なマルチテラバイトテーブルであっても効率的に正確な統計情報を計算し、Aurora DSQL が事実上無制限のテーブルサイズにスケールできるようにします。

確率的トリガー

Aurora DSQL は、テーブル統計情報をいつ更新するかを決定するために、Auto Analyze の確率的トリガーを使用します。コミットする各トランザクションは、テーブルサイズと挿入、更新、削除操作を通じて行う変更数に依存するANALYZEをトリガーする確率を持ちます。ANALYZEのトリガーはトランザクションのパフォーマンスに大きな影響を与えないことに注意してください。このセクションでは、トランザクションのANALYZE確率がどのように決定されるかを説明します。

Aurora DSQL は各トランザクション内でテーブルごとの変更を追跡します。トランザクションがコミットされると、変更された各テーブルが 10% の閾値比に対して評価されます。トランザクションがテーブルの行の 10% 以上を変更する場合、ANALYZEは常にトリガーされます。より小さな変更の場合、ANALYZEをトリガーする確率は変更された行の割合に比例します。

Let threshold_ratio = 0.1
for each modified table R:
    change_count = num_inserts + num_updates + num_deletes
    threshold_count = threshold_ratio * pg_class.reltuples(R)
    probability = change_count / threshold_count
    if random_number(0,1) <= probability:
        submit_job("ANALYZE R")

この説明は現在、100万行以上のテーブルについてのみ正確です。より小さなテーブルについては、Aurora DSQLの別のクエリプロセッサで実行されるANALYZEのセットアップコストを考慮した減衰係数があります。

この確率的アプローチは、データベースセッション間の調整を必要とせずに、平均してテーブルの 10% が変更された後にANALYZEをトリガーします。システムは、確率を計算するためにpg_class.reltuples(以前のANALYZE実行によって設定される) からの行数推定値を使用し、分析されていないテーブルについてはデフォルトで1行とします。

確率的メカニズムはワークロードパターンに自然に適応します。頻繁に変更されるテーブルでは、統計情報がより頻繁に更新されます。逆に、静的なテーブルでは不要なANALYZEオーバーヘッドを回避します。

サンプリングベースの ANALYZE

Aurora DSQL がANALYZE操作をトリガーすると、テーブル全体をスキャンすることなく効率的に正確な統計情報を計算するためにサンプリングを使用します。システムは最低30,000行のサンプルを収集するように設計されたサンプリング率を計算し、大きなテーブルではさらに多くの行を収集します。このサンプルはpg_classのテーブル全体の統計情報を計算するために使用されます。その後、PostgreSQLと同様に、厳密な30,000行のサブセットが列固有の統計情報を生成するために使用されます。

私たちの手法は、計算された確率に基づいてストレージから行をランダムに選択することで機能します。このアプローチは PostgreSQL のサンプリング手法を反映しながら、Aurora DSQL の分散アーキテクチャに適応しています。サンプリング率は、以前の統計情報から推定されるテーブルサイズに対する目標行数によって決定されます。

前述したように、収集されたサンプルは2種類の統計情報を生成します:pg_classに格納されるテーブル全体の統計情報と、pg_stats の列固有の統計情報です。テーブル全体の推定値は行数とページ数の推定値です。pg_statsの列固有の統計情報には、null値の割合、個別値の比率、ヒストグラム、最頻値が含まれます。これらの統計情報は、効率的な実行プランを生成するために必要な情報をクエリオプティマイザーに提供します。

Aurora DSQLが使用するサンプリングベースの Analyze 手法は、テーブルの成長に関係なく一貫したサンプルサイズを提供することで、マルチテラバイトのテーブルであっても効率的な計算を保証します。実験では、最大240TBまでのあらゆるサイズのテーブルでANALYZEが数分で完了することがわかりました。

まとめ

この投稿では、Aurora DSQL の Auto Analyze 機能について学びました。Auto Analyze は、分散マルチリージョンデータベースシステム特有の課題に対処しながら、PostgreSQL の autovacuum による ANALYZE の信頼性を提供します。確率的トリガーと効率的なサンプリングベースの計算を組み合わせることで、手動介入なしにクエリが適切に維持された統計情報から一貫して恩恵を受けることができます。確率的アプローチは、従来の閾値ベースのシステムが必要とする調整オーバーヘッドの多くを排除し、分散アーキテクチャに自然に適しています。一方、サンプリングベースの分析は、小さなテーブルから大規模な 240TB のデータセットまでスケールします。Aurora DSQL Auto Analyze は、バックグラウンドで透過的に動作しながら、適切に維持されたオプティマイザー統計情報の利点を提供し、開発者がテーブル統計の管理ではなくアプリケーションの構築に集中できるようにします。

Aurora DSQL Auto Analyze は、Aurora DSQLが利用可能なすべてのリージョンで利用できます。Aurora DSQL の詳細については、ウェブページドキュメントをご覧ください。


Magnus Mueller

Magnus Mueller

Magnus は AWS の応用科学者で、カーディナリティ推定、クエリ最適化、システム向け機械学習を専門としています。カーディナリティ推定の博士号を取得し、主要なデータベース会議で研究を発表しています。

James Morle

James Morle

James はプリンシパルエンジニア兼分散データベースアーキテクトで、ハイパースケールでの大規模トランザクショナル・分析システムの設計・実装において 20 年以上の経験を持ちます。

Matthys Strydom

Matthys Strydom

Matthys は AWS のプリンシパルエンジニアで、分散データベースクエリ処理、AWS クラウドサービスコントロールプレーン、高スループット電話網統合、デスクトップCADプログラムなど、幅広いソフトウェアシステムにおいて 20 年以上の経験を持ちます。

Vishwas Karthiveerya

Vishwas Karthiveerya

Vishwas は AWS のシニアソフトウェア開発・データベースシステムエンジニアで、大規模分散データベースのクエリプランニング、コストベース最適化、実行性能を専門としています。

Raluca Constantin

Raluca Constantin

Raluca は AWSのシニアデータベースエンジニアで、Amazon Aurora DSQL を専門としています。Oracle、MySQL、PostgreSQL およびクラウドネイティブソリューションにわたる 18年のデータベース専門知識を持ち、データベースのスケーラビリティ、性能、リアルタイムデータ処理に焦点を当てています。

翻訳はソリューションアーキテクトの伊津野安梨沙が担当しました。原文はこちらです。