このトピックでは、PolarDB for PostgreSQL のテーブルサイズキャッシュ機能について説明します。
背景情報
データベースにおける SQL 文の実行ライフサイクル中は、関連するシステムテーブルとユーザテーブル、およびそれらのインデックスに複数回アクセスします。このプロセス中に、PolarDB for PostgreSQL は、ストレージマネージャ smgr の smgrnblocks
関数を呼び出すことによって、テーブルファイルが占有するブロック数を頻繁にクエリします。smgrnblocks
関数は、ファイルシステムの lseek
関数を呼び出してファイルサイズをクエリし、それをブロックサイズに基づいてブロック数を計算するために使用します。ただし、smgrnblocks
関数は、SQL 処理のクリティカルパス上にあります。ファイルシステムの関数を頻繁に呼び出すと、データベースのパフォーマンスに深刻な影響を与えます。この問題は、分散 Polar ファイルシステム (PolarFS) を使用する PolarDB for PostgreSQL ではさらに悪化します。集中型ファイルシステムと比較して、PolarFS は lseek
関数の呼び出しでより高いレイテンシを示します。これにより、SQL 文の実行時間が長くなります。
ファイルシステムの呼び出しを最小限に抑えるために、PolarDB for PostgreSQL は、smgr 内にリレーションサイズキャッシュ (RSC) を実装して、各テーブルファイルが占有するブロック数を共有メモリに格納します。テーブルが占有するブロック数が変更されると、共有メモリ内のキャッシュ値がそれに応じて更新されます。RSC は、テーブルファイルが占有するブロック数をクエリするために優先的に使用されます。これにより、ファイルシステムの呼び出し回数が減り、SQL の実行が高速化されます。
前提条件
PolarDB for PostgreSQL クラスタは、次のデータベースエンジンバージョンのいずれかを実行している必要があります。
リビジョンバージョンが 2.0.16.3.1.1 以降の PolarDB for PostgreSQL 16。
リビジョンバージョンが 2.0.15.7.1.1 以降の PolarDB for PostgreSQL 15。
リビジョンバージョンが 2.0.14.12.23.1 以降の PolarDB for PostgreSQL 14。
[コンソール] でリビジョンバージョンを表示するか、SHOW polardb_version;
文を実行して表示します。必要に応じて、リビジョンバージョンをアップグレードします。
機能説明
RSC クエリ
RSC は、共有メモリ内にある 1 次元配列とハッシュテーブルで構成されます。
1 次元配列の各キャッシュエントリには、テーブルやインデックスなどのリレーションが占有するブロック数が格納されます。
ハッシュテーブルは、RelFileNode 値と呼ばれるリレーション識別子を、1 次元配列内の対応するキャッシュエントリにマッピングします。RelFileNode 値は、ストレージレイヤーでリレーションを一意に識別します。
すべてのプロセスは、次の 2 つのレベルのインデックスを順番に使用して RSC をクエリしようとします。
レベル 1 インデックス: このインデックスは、最近アクセスされた RSC キャッシュエントリへのポインタと、対応する世代番号をキャッシュします。プロセスがテーブルに関する情報をリクエストすると、最初にレベル 1 インデックスがチェックされます。リクエストされたテーブルがレベル 1 インデックスに格納されているテーブルと一致し、ポインタに対応する RSC キャッシュエントリの世代番号が変更されていない場合、プロセスはポインタを使用してテーブルが占有するブロック数を直接取得できます。特定のテーブルの読み取りと書き込みの比率が高いシナリオでは、レベル 1 インデックスによって高いヒット率が保証されます。RSC ハッシュテーブルのマッピングに変更が発生した場合、ハッシュテーブルを更新し、影響を受ける RSC キャッシュエントリの世代番号を自動的に増分する必要があります。このメカニズムにより、レベル 1 インデックスの古いデータが無効になります。
レベル 2 インデックス: レベル 1 インデックスに必要な情報が含まれていない場合 (キャッシュミスを示す)、プロセスはレベル 2 インデックスをチェックします。このインデックスは、共有メモリ内のハッシュテーブルをクエリして、必要なテーブルに対応する RSC キャッシュエントリを取得します。キャッシュエントリが見つかると、プロセスはテーブルが占有するブロック数を取得し、レベル 1 インデックスを更新します。
上記の 2 つのレベルのインデックスを使用して RSC でテーブルと対応するブロック数をクエリできない場合は、キャッシュ置換メカニズムがトリガーされます。このメカニズムは、セグメント化された LRU (SLRU) アルゴリズムを使用して、最近使用されていない RSC キャッシュエントリを選択してクリアします。その後、ファイルシステムの lseek
関数が呼び出されて、実際のブロック数が判別されます。この数は、以前にクリアされた RSC キャッシュエントリに更新され、2 つのレベルのインデックスが同期的に更新されます。
プライマリノードとスタンバイノードでの RSC 更新
RSC 機能が有効になっている場合、smgr の関数を呼び出してテーブルのサイズを変更するには、共有メモリ内の関連する RSC キャッシュエントリを同期的に更新する必要があります。これにより、キャッシュされたテーブルのブロック数が、ファイルシステム内のテーブルが実際に占有しているブロック数と同じになります。
関数を呼び出してテーブルを拡張する場合、拡張されたテーブルが占有するブロック数を RSC に更新する必要があります。
関数を呼び出してテーブルを切り捨てる場合、切り捨てられたテーブルが占有するブロック数を RSC に更新する必要があります。
スタンバイノードは、物理レプリケーションを使用してプライマリノードと同期を維持します。WAL (Write Ahead Log) レコードの再生中に、スタンバイノードは smgr の同じ関数を呼び出してテーブルサイズを変更します。したがって、RSC の更新はプライマリノードとスタンバイノードで同じように処理されます。
レプリカノードでの RSC 更新
レプリカノードはプライマリノードと物理ストレージを共有し、ログインデックスを使用してプライマリノードと同期を維持します。レプリカノードは、ストレージに書き込み操作を実行しません。したがって、smgr の関数を呼び出して共有メモリ内の RSC 値を更新することはできません。
共有ストレージでファイルサイズが変更されたかどうかを判断するために、レプリカノードは WAL レコードで参照されるデータブロックのシーケンス番号を解析し、シーケンス番号を RSC に格納されているブロック数と比較します。WAL レコードがキャッシュされたブロック数よりも高いブロックシーケンス番号を参照している場合、キャッシュされたブロック数は実際のブロック数を反映するように更新されます。テーブルの切り捨てを示す WAL レコードが解析されると、RSC 内のキャッシュされたブロック数は無効になります。次回、ファイルシステムの関数が呼び出されて切り捨てられたテーブルが占有するブロック数が取得されると、RSC に実際のブロック数が再入力されます。
使用上の注意
Grand Unified Configuration (GUC) パラメータ
次の表に、RSC によって提供される GUC パラメータを示します。
パラメータ | 説明 |
polar_enable_rel_size_cache | RSC 機能を有効にするかどうかを指定します。有効な値:
|
polar_enable_replica_rel_size_cache | レプリカノードの RSC 機能を有効にするかどうかを指定します。有効な値:
|
polar_enable_standby_rel_size_cache | スタンバイノードの RSC 機能を有効にするかどうかを指定します。有効な値:
|
パフォーマンステスト
RSC 機能が無効になっている場合、32 GB のテーブルが占有するブロック数をクエリする際のレイテンシは約 55 マイクロ秒です。
SHOW polar_enable_rel_size_cache; polar_enable_rel_size_cache ----------------------------- off (1 row) SELECT polar_smgrperf_nblocks(32, true, false); NOTICE: testing logical file length with 32 GB INFO: iops=18341.1/s, lat=54.52us INFO: iops=17504.0/s, lat=57.13us INFO: iops=17960.8/s, lat=55.68us INFO: iops=17973.0/s, lat=55.64us INFO: iops=17603.5/s, lat=56.81us INFO: iops=17403.8/s, lat=57.46us INFO: iops=17506.2/s, lat=57.12us INFO: iops=18061.7/s, lat=55.37us
RSC 機能が有効になっている場合、32 GB のテーブルが占有するブロック数をクエリする際のレイテンシは約 0.07 マイクロ秒です。
SHOW polar_enable_rel_size_cache; polar_enable_rel_size_cache ----------------------------- on (1 row) SELECT polar_smgrperf_nblocks(32, true, false); NOTICE: testing logical file length with 32 GB INFO: iops=14155515.6/s, lat=0.07us INFO: iops=13897273.6/s, lat=0.07us INFO: iops=13869926.3/s, lat=0.07us INFO: iops=13779602.7/s, lat=0.07us INFO: iops=14159120.5/s, lat=0.07us INFO: iops=14147065.6/s, lat=0.07us INFO: iops=14124141.9/s, lat=0.07us INFO: iops=14162773.3/s, lat=0.07us