PostgreSQL では、パーティションテーブルはデータ増加を管理する効果的な方法であり、パーティションプルーニングはクエリを高速化するのに役立ちます。PolarDB for PostgreSQL の列ストアインデックスもパーティションテーブルをサポートしており、これらのテーブルの統計および分析ニーズにさらに応えます。
背景情報
業務システムの実行に伴い、大量の既存データが生成され、テーブルが肥大化します。データは通常、時間や user_id などのディメンションでパーティション分割され、各パーティションにはデータのサブセットのみが格納されます。ネイティブの PostgreSQL でも、クエリ中にパーティションプルーニングを使用して、無関係なデータの読み取りを回避します。
PolarDB for PostgreSQL の列ストアインデックスは、パーティションテーブルでの分析の高速化もサポートしています。パーティションテーブル上の既存のインデックスと同じ方法で使用できます。
結果
並列処理の次数が 4 の場合、列ストアインデックスは 3 つのクエリすべてにおいて、ネイティブの PostgreSQL の並列実行よりも 35 倍以上高速に実行されます。
クエリ | ネイティブの PostgreSQL の並列実行 | 列ストアインデックス |
Q1 | 2.13 秒 | 0.05 秒 |
Q2 | 6.42 秒 | 0.18 秒 |
Q3 | 10.51 秒 | 0.30 秒 |
操作手順
ステップ 1:環境の準備
クラスターのバージョンと構成が次の要件を満たしていることを確認します。
クラスターバージョン:
PostgreSQL 16 (マイナーエンジンバージョン 2.0.16.8.3.0 以降)
PostgreSQL 14 (マイナーエンジンバージョン 2.0.14.10.20.0 以降)
説明コンソールで、または
SHOW polardb_version;文を実行することで、マイナーエンジンバージョン番号を確認できます。マイナーエンジンバージョンが要件を満たさない場合は、マイナーエンジンバージョンをアップグレードする必要があります。ソーステーブルにはプライマリキーが必要です。列ストアインデックスを作成する際には、プライマリキー列を含める必要があります。
wal_levelパラメーターをlogicalに設定する必要があります。これにより、論理レプリケーションをサポートするために必要な情報が先行書き込みログ (WAL) に追加されます。説明wal_level パラメーターはコンソールで設定できます。このパラメーターを変更すると、クラスターが再起動します。ビジネス運用を適切に計画し、注意して進めてください。
列ストアインデックス機能を有効にします。
PolarDB for PostgreSQL クラスターのマイナーエンジンバージョンによって、列ストアインデックス機能を有効にする方法が異なります。
ステップ 2:データの準備
この例では、多階層パーティションテーブルを作成し、3 億 2000 万行のシミュレーションデータ (約 16 GB) を挿入します。その後、パーティション条件に基づいて統計分析を実行します。
テスト用のパーティションテーブルのスキーマは次のとおりです。
sales:プライマリテーブル。sales_2023:年でパーティション分割。sales_2023_a:月でパーティション分割。このパーティションには 1 月から 6 月までのデータが含まれます。sales_2023_b:月でパーティション分割。このパーティションには 7 月から 12 月までのデータが含まれます。
sales_2024:年でパーティション分割。sales_2024_a:月でパーティション分割。このパーティションには 1 月から 6 月までのデータが含まれます。sales_2024_b:月でパーティション分割。このパーティションには 7 月から 12 月までのデータが含まれます。
salesという名前の多階層パーティションテーブルを作成します。sale_date列をパーティションキーとして使用します。定義は次のとおりです。CREATE TABLE sales ( sale_id serial, product_id int NOT NULL, sale_date date NOT NULL, amount numeric(10,2) NOT NULL, primary key(sale_id, sale_date) ) PARTITION BY RANGE (sale_date); CREATE TABLE sales_2023 PARTITION OF sales FOR VALUES FROM ('2023-1-1') TO ('2024-1-1') PARTITION BY RANGE (sale_date); CREATE TABLE sales_2023_a PARTITION OF sales_2023 FOR VALUES FROM ('2023-1-1') TO ('2023-7-1'); CREATE TABLE sales_2023_b PARTITION OF sales_2023 FOR VALUES FROM ('2023-7-1') TO ('2024-1-1'); CREATE TABLE sales_2024 PARTITION OF sales FOR VALUES FROM ('2024-1-1') TO ('2025-1-1') PARTITION BY RANGE (sale_date); CREATE TABLE sales_2024_a PARTITION OF sales_2024 FOR VALUES FROM ('2024-1-1') TO ('2024-7-1'); CREATE TABLE sales_2024_b PARTITION OF sales_2024 FOR VALUES FROM ('2024-7-1') TO ('2025-1-1');約 16 GB のデータを生成し、パーティションテーブルに挿入します。
INSERT INTO sales (product_id, sale_date, amount) SELECT (random()*100)::int AS product_id, '2023-01-1'::date + i/3200000*7 AS sale_date, (random()*1000)::numeric(10,2) AS amount FROM generate_series(1, 320000000) i;テーブルに列ストアインデックスを作成します。
sale_id、product_id、sale_date、amountフィールドを列ストアインデックスに追加します。CREATE INDEX ON sales USING CSI(sale_id, product_id, sale_date, amount);
ステップ 3:クエリの実行
異なる実行エンジンを使用してクエリを実行します。異なるパーティション条件に基づいて、Q1、Q2、Q3 の 3 つのクエリが生成されます。
列ストアインデックスの使用
--- 列ストアインデックスを有効にし、クエリの並列処理の次数を 4 に設定します。 SET polar_csi.enable_query to on; SET polar_csi.exec_parallel to 4; --- Q1 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-3-1' AND amount > 100 GROUP BY sale_date; --- Q2 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-9-1' AND amount > 100 GROUP BY sale_date; --- Q3 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2024-3-1' AND amount > 100 GROUP BY sale_date;列ストアインデックスを無効にし、ローストアエンジンを使用
--- 列ストアインデックスを無効にし、ローストアエンジンを使用して、クエリの並列処理の次数を 4 に設定します。 SET polar_csi.enable_query to off; SET max_parallel_workers_per_gather to 4; --- Q1 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-3-1' AND amount > 100 GROUP BY sale_date; --- Q2 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2023-9-1' AND amount > 100 GROUP BY sale_date; --- Q3 EXPLAIN ANALYZE SELECT sale_date, COUNT(*) FROM sales WHERE sale_date BETWEEN '2023-1-1' and '2024-3-1' AND amount > 100 GROUP BY sale_date;





