Cloud Native Practice of MPP Architecture Data Warehouse
1. はじめに
Garner の予測によると、2022 年までに全データベースの 75% がクラウドプラットフォームにデプロイまたは移行されます。もう一つの権威ある機関である IDC も、2025 年までにデータベースの 50% 以上がパブリッククラウドにデプロイされ、中国は驚くべき 70% 以上に達すると予測しています。長年の発展を経て、クラウドデータベースは Cloud-Hosted(クラウドホスティング)から Cloud Native(クラウドネイティブ)モデルへと変革を遂げました。
Cloud-Hosted: 市場および業界のクラウド要件に基づき、ほとんどのベンダーはクラウドホスティングを進化の第一歩として選択しています。このモデルでは、ユーザーがオフラインで独自の IDC を構築する必要がなくなり、クラウドプロバイダーの標準化されたリソースに依存してデータウェアハウスを移行し、高度なホスティングを提供することで、ユーザーを基盤ハードウェアの管理コストや Lingplan リソースの制約から解放します。
Cloud-Native: しかし、より多くのビジネスがクラウドに移行されるにつれ、基盤のコンピューティングリソースとストレージリソースが一体化されているため、ユーザーは使用時にリソースの不要な浪費を考慮する必要が生じます。たとえば、コンピューティングリソースの増加はストレージの関連増加を必要とし、無効なコストが発生します。ユーザーはクラウドリソースがよりきめ細かい方法でデータウェアハウスリソースを分解できることを期待し始めます。つまり、コンピューティング機能とストレージ機能を分離し、ビジネスのリソースオーケストレーションを満たすために販売可能な単位に分割することです。この時点で、クラウドネイティブの最大の価値が真に発揮されます。ストレージと計算のバランスが取れたデータウェアハウスの構築に注力するのではなく、ユーザービジネスに向き合い、大規模なコンピューティングまたはストレージの傾斜を可能にし、ビジネスに必要なリソースを独立してデプロイします。最小単位でデプロイおよび販売します。この瞬間、真にデータウェアハウスのクラウドネイティブ時代に入ったと言えます。
2021 年の雲栖大会で、Alibaba Cloud は新しいクラウドネイティブアーキテクチャのデータウェアハウスを発表しました [1]。本記事では、クラウドネイティブデータウェアハウスプロダクト AnalyticDB PostgreSQL(以下 ADB PG と称する)の Cloud-Hosted から Cloud-Native への進化と探求を紹介し、真のリソースプーリングと柔軟な販売を実現するための基盤設計と考え方を議論します。アーキテクチャ設計、主要技術、パフォーマンス結果、効果実現、および今後の計画を含みます。(全文の読了時間は約 10 分です)
2. ADB PG クラウドネイティブアーキテクチャ
ユーザーがクラウドデータウェアハウスに迅速に適応できるように、現在クラウド上で MPP アーキテクチャの設計コンセプトを採用し、コーディネーションノードとコンピューティングノードを独立してデプロイしていますが、単一の ECS 上にそれらを載せ、コンピューティングノードのストレージとコンピューティングの統合デプロイメント設計を実現しています。この設計アーキテクチャはクライアント側で高度に適応可能でセルフビルドされており、データウェアハウスビジネスをクラウドに迅速かつ非破壊的に移行できるため、初期のクラウド適応に非常にフレンドリーで、リソースの並列拡張という主要要件を満たしています。
クラウドネイティブのさらなる進化に伴い、全新的なストレージとコンピューティングの分離アーキテクチャを提供し、プロダクトをサービス層、コンピューティング層、および共有ストレージ層にさらに分割しました。アーキテクチャ図は以下の通りです:
マスターコーディネーションノード: グローバルスキーマ情報を保存し、グローバルトランザクション管理を実現します。
行ストレージエンジン: メタデータ情報を保存するために使用され、メタデータ情報は主に共有ストレージファイルの可視性情報を指し、2 つの部分を含みます:
1 つはファイルとテーブルの関係です
もう 1 つは削除されたデータの削除ビットマップです
行ストレージに基づいて、PG のローカルトランザクション機能を継承でき、追加・削除・更新・参照の際に PG のトランザクション機能と完全に互換性があります。
ローカルキャッシュ: ストレージチームの DADI を導入することで高性能なローカルキャッシュを実現します。DADI の正式名称は Alibaba Cloud Data Accelerator for Disaggregated Infrastructure です。オープンソースプロダクトと比較して、パフォーマンスは桁違いに向上しています。
共有ストレージ: ClickHouse からいくつかの重要な設計を借用し、ストレージ層で MergeTree ベースの行列混合ストレージを実装しました。さらに、ファイルインターフェースに基づいた統一アクセスインターフェースを作成し、OSS と HDFS の両方と高度に互換性のある様々な形式の分散ファイルシステムに対応しています。
アーキテクチャを設計する際、同じく Greenplum から派生した HAWQ と比較すると、HAWQ はメタデータをマスターに保存します。書き込みのたびに、変更されたメタデータをマスターに持って更新します。読み取り時はマスターから必要なメタデータを読み取り、すべてのメタデータを実行計画に含めることで、セグメントが対応するメタデータを取得でき、セグメントを完全にステートレスにできます。
しかし、この設計には 2 つの核心的な問題が生じます:
メタデータの膨張により、マスターがボトルネックになる。
メタデータのパフォーマンスに制限され、高い同時実行性のリアルタイム書き込みをサポートできない。
このように設計しなかった理由は、将来的に高い同時実行性タスクをサポートしたいからです。ADB PG は 2 年以上かけて Greenplum の単一ポイントマスターアーキテクチャをマルチマスターに拡張しました。核心は高い同時実行性タスクのリアルタイム書き込み問題を解決することです。メタデータがマスターに保存されていると、以下のような問題が発生します:
マスター上のメタデータのストレージとアクセスが単一ポイントのボトルネックを形成しやすい
ADB PG の実行層でメタデータを実行計画に組み込むための大規模なリファクタリングが必要であり、クエリプラン自体の帯域幅が劇的に増加するため、高い同時実行性を持つ小規模クエリに非常に不利です。
そこでアーキテクチャを改善し、メタデータをセグメントに分散することで、以下を実現しました:
マスターのストレージと読み書きがボトルネックにならない
実行層のリファクタリングが不要で、メタデータを分散することで単一のクエリの帯域幅圧力を軽減
メタデータをセグメント上の分散 KV に配置し、スケールアウト/スケールイン時のメタデータ再配置の問題を解決
共有ストレージに OSS を使用する理由は、単一ユーザーのビジネスデータが継続的に増加するにつれ、持続可能なストレージソリューションが必要であり、OSS の低ストレージコスト、高可用性、データの永続性が最適な選択だからです。
OSS を使用するもう 1 つの利点は、オンデマンドで課金されることです。ユーザーはストレージスペースのサイズを事前に設定する必要がなく、保存されているデータ量に応じて課金されます。データが削除されると課金されません。ESSD クラウドディスクは通常データに基づいてストレージ水位を計算する必要があり、ストレージリソースの真のオンデマンド供給を行うことができず、容量の自動縮小もできません。これらすべてがクラウドネイティブの設計思想に反します。しかし同時に、OSS の欠点は RT です:
OSS の RT 問題を解決するために、コンピューティングノードに一定割合のローカルディスクを設定し、アクセス高速化を図っています。さらに、ClickHouse の MergeTree ストレージの核心思想を参考にした高性能な行列混合ストレージを設計しました。順序を核心とし、ファイルは絶対的に順序付けされ、ファイル内は相対的に順序付けされています。マージの非同期操作により、ファイルのマージとソートを実現し、順序付けに基づいてファイル内に 3 層の統計情報を設計し、大量の IO クリッピング最適化を行いました。
以下、各技術ポイントをさらに詳しく紹介します。
3. 主要技術
1. 弾力的スケーリング
高速な弾力的スケーリングを実現するために、私たちの方法は共有ストレージ上でデータをハッシュバケットで整理することです。スケーリング後、コンピューティングノードとバケットをコンシステントハッシュで再マッピングします。バケットとセグメントの割り当ての均一性を解決し、スケーリング後のキャッシュ失敗の影響を低減するために、従来のコンシステントハッシュアルゴリズムを改善し、スケーリング中の動的マッピングをサポートしました。
データをハッシュバケットに従って複数のシャードに分割し、オブジェクトストレージ上のデータをシャーディング粒度で再マッピングします。コンピューティングノードの拡張がシャード数を超えた場合、データを再配布する必要があります。この問題を解決するために、バックグラウンドでハッシュバケットの分割とマージをサポートし、データの再配布を回避します。
以上がスケーリング時の「データ」の再マッピングであり、データファイルの可視性を記述するメタデータは行テーブルに保存されます。Greenplum のデータ再配布戦略を引き続き使用していますが、メタデータの再配布を高速化するために、並列配布などの最適化を行っています。
容量拡張を例にとって、容量拡張のプロセスをさらに詳しく説明します:
ECS リソースプーリング、ネットワークカードの並列ロード、Docker イメージの予熱などの技術と組み合わせ、16 ノード以内のエンドツーエンドの所要時間は約 1 分です。
2. 階層ストレージ
階層ストレージの実装は以下の通りです:
上記の図に示すように、ストレージリソースをメモリ、ローカルディスク、共有ストレージの 3 層に分割します。
メモリ: 主に行ストレージアクセスの高速化とファイル統計情報のキャッシュを担当します。
ローカルディスク: 行ストレージの永続ストレージとして、およびリモート共有ストレージのローカルアクセラレータとして使用します。
リモート共有ストレージ: データの永続ストレージとして使用します。
3. 読み書きプロセス
書き込みプロセスは以下の通りです:
ユーザーが書き込んだデータは、データバッチングを通じて OSS に直接書き込まれ、同時にローカルディスクにメタデータが記録されます。このメタデータはファイルとデータテーブルの対応関係を記録します。メタデータは PG の行ストレージテーブルを使用して実装され、ファイルメタデータテーブルを通じてこの情報を保存します。
更新または削除時、OSS 上のデータを直接変更する必要はありません。削除マークを付けることで対応します。削除マークの情報もローカル行ストレージテーブルに保存され、可視性ビットマップを通じてこの情報を保存します。削除マークは読み取りパフォーマンスの低下を招くため、バックグラウンドマージを使用して削除情報をファイルに適用し、読み取りパフォーマンスへの影響を低減します。
書き込み時、セグメント上のデータをバケットに従ってさらに分割し、これにより小さなファイルの問題が発生します。小さなファイルの問題を解決するために、以下の最適化を行いました:
グループフラッシュ: 書き込みデータのバッチをグループフラッシュを通じて同じ OSS ファイルに書き込めます。OSS ファイルは ORC フォーマットを採用し、異なるバケットは対応するストライプに書き込まれます。
パイプラインの非同期並列処理: エンコーディングとソーティングは典型的な CPU 集約型タスクであり、OSS へのアップロードは典型的なネットワーク IO 集約型タスクです。これらの 2 種類のタスクを並列化し、OSS アップロードタスクを非同期タスクとして実行します。同時に次のバッチのデータのエンコーディングとソーティングを行い、書き込みパフォーマンスを高速化します。
リモート永続ストレージは 12 個の 9 の永続性を提供するため、メタデータを保存する行ストレージのみが WAL ログとダブルコピーで信頼性を確保します。データ自体は WAL ログと複数コピーなしで共有ストレージに書き込まれます。WAL ログの削減、WAL ログのマスター・スレーブ同期の削減、および非同期並列処理とバッチ蓄積により、バッチ書き込みシナリオでは、書き込みパフォーマンスは基本的に ECS 弾性ストレージバージョンと同等です。
読み取りプロセスは以下の通りです:
ファイルメタデータテーブルを読み取ることで、スキャン対象の OSS ファイルを取得します。
OSS ファイルに従って対応するファイルを読み取ります。
読み取ったファイルは、メタデータテーブルの可視性ビットマップを通じて削除されたデータをフィルタリングします。
OSS 読み取りによる遅延を解決するために、DADI も導入し、キャッシュ管理の実装と共有ファイルアクセスのカプセル化を支援しています。ファイル読み取り時にまずローカルキャッシュの有無を判断し、あればローカルディスクから直接読み取ります。なければ OSS に読み取りに行き、読み取り後にローカルにキャッシュされます。書き込み時は OSS に直接書き込み、ローカルディスクにライトバックします。ライトバックは非同期操作です。DADI を通じてローカルキャッシュデータの淘汰も管理しており、LRU/LFU 戦略に従ってコールドデータを自動的に淘汰します。
トランザクションは PG の行ストレージを使用して実装されているため、ADB PG のトランザクションと完全に互換性があります。問題は、スケーリング時にこの部分のデータを再配布する必要があることです。このデータの再配布メカニズムを再設計し、事前パーティショニング、並列コピー、ポイントツーポイントコピーなどの技術を通じて、スケーリング時間を大幅に短縮しました。
パフォーマンス最適化ポイントをまとめると:
ローカル行ストレージテーブルを通じてトランザクション ACID を実現し、データブロックレベルの同時実行性をサポート。
バッチとパイプラインの並列化により書き込みスループットを向上。
DADI に基づくメモリとローカル SSD のマルチレベルキャッシュによるアクセス高速化。
4. 可視性テーブル
共有ストレージファイルに関連する情報をファイルメタデータに保存します。その構造は以下の通りです:
ハッシュバケット: スケーリング時のデータ再配置時にバケットに従ってスキャンするために使用されます。クエリ時にもバケットに従ってバケットごとに処理されます。
レベル: マージツリーのレベルです。レベル 0 はリアルタイムに書き込まれたデータを表し、この部分のデータはマージ時に高い重みを持ちます。
物理ファイル ID: ファイルに対応する ID です。64 バイトで、セグメントとの関連がなくなり、セグメント内のテーブルの一意性を保証するだけでなく、グローバルに一意である必要があります。
ストライプ ID: 1 つの OSS ファイルに複数のバケットファイルを含めることができるため、ストライプを単位として、セグメントで書き込まれた複数のバケットを 1 つの OSS ファイルにマージするのに便利です。小さな OSS ファイルによるパフォーマンス低下や、小さな OSS ファイルの爆発を回避します。
合計カウント: ファイルの行数で、バックグラウンドマージの重みでもあります。大きいほどマージ重みが低くなります。
可視性ビットマップは削除されたファイル情報を記録します。
Start_row は 32k に対応し、削除ビットマップに対応します。この 32000 4k で、行ストレージが使用する 32k ページは 7 つのレコードを保存できます。
Delete count は削除された数です。
OSS にアクセスする必要なく、マージが必要なファイルを直接取得でき、OSS へのアクセスによる遅延を回避します。OSS もスループットに制限があるため、頻繁なアクセスによる OSS のフロー制限のトリガーを回避できます。
5. 行列混合ストレージ
MergeTree の構造は上記の図の左側に示されています。核心はバックグラウンドマージ方式で小さなファイルを大きな順序付きファイルにマージすることであり、マージ時にデータを再配置できます。たとえば、データの順序特性を変更してさらなる最適化を行います。順序感知最適化については後述を参照してください。leveldb との違いは:
レイヤー 0 のリアルタイム書き込みはマージされ、異なるバケットのファイルは大きなファイルにマージされ、異なるバケットは対応するストライプに落ちます。
マージはレイヤーをまたいでマージ条件を満たすファイルをマージします。ファイルは厳密に順序付けられていますが、ファイル間はおおまかに順序付けられています。レイヤー数が高いほどファイルは大きくなり、ファイル間の重複は小さくなります。
各ファイルに行列混合ストレージフォーマットを使用しており、行列混合ストレージの具体的なストレージフォーマットは右側にあります。ORC 基礎上で多くの最適化を行いました。
ORC ファイル: 1 つの ORC ファイルに複数のストライプを含めることができ、各ストライプには複数の行グループが含まれ、各行グループには固定レコードが含まれ、これらのレコードは列ごとに独立して保存されます。
PostScript: ファイルの説明情報 PostScript、ファイルメタ情報(ファイル全体の統計情報、データディクショナリなどを含む)、すべてのストライプ情報、およびファイルスキーマ情報を含みます。
ストライプ: ストライプは行の分割で、行をグループ化してストライプを形成し、読み取りファイルは行グループ単位で行われ、各列のインデックスとデータを保存します。インデックスデータ、行データ、およびストライプフッターで構成されます。
ファイルフッター: ストライプの位置、ストライプ内の各列の統計情報、およびすべてのストリームタイプと位置を保存します。
インデックスデータ: 行グループレベルの統計情報を保存します。
データストリーム: ストリームはファイル内の有効なデータピースを表し、インデックスとデータを含みます。
インデックスストリームは各行グループの位置と統計情報を保存します。データストリームは複数のタイプのデータを含み、具体的なタイプは列タイプとエンコーディング方式によって決まります。以下、整数と文字列の 2 つのタイプを例として示します:
整数フィールドの場合、ビットストリームと整数ストリームの両方が使用されます。ビットストリームは特定の値が null かどうかを識別するために使用され、整数ストリームは整数フィールドの null でないレコードの整数値を保存するために使用されます。
文字列タイプフィールドの場合、ORC ライターはフィールド値の異なるコンテンツ数が null でないレコードの総数の 80% 以下であるかどうかをチェックし、辞書エンコーディングを使用します。フィールド値はビットストリーム、バイトストリーム、および 2 つの整数ストリームに保存されます。ビットストリームは null 値の識別にも使用され、バイトストリームは辞書値の保存に使用され、1 つの整数ストリームは辞書の各エントリの長さを保存し、もう 1 つの整数ストリームはフィールド値を記録するために使用されます。辞書エンコーディングを使用できない場合、ORC ライターはこのフィールドの繰り返し値が少なすぎて辞書エンコーディングの効率が低いことを認識します。ORC ライターはバイトストリームを使用して String フィールドの値を保存し、整数ストリームを使用して各フィールドのバイト長を保存します。
ORC ファイルには 3 層の統計情報が保存されており、それぞれファイルレベル、ストライプレベル、行グループレベルです。ストレージパフォーマンス向上の核心は IO を削減することです。ORC の統計情報とインデックスに基づいて様々なプッシュダウンを実装し、IO クリッピングを実現しています。たとえば、Projection プッシュダウンでは、マテリアライズが必要な列のみをスキャンします。Agg プッシュダウンでは、必要な min、max、sum、unique を統計情報またはインデックスから直接読み取って返します。データストリームの解凍を回避します。述語についても、フィルタのプッシュダウンをサポートし、統計情報を通じて直接フィルタリングし、条件を満たさないストライプを直接スキップします。様々な演算子、in/not in、および式の等価変換をサポートしています。
さらに、ストレージフォーマットのパフォーマンスを以下のように最適化しました:
ゼロコピー: ORC データ型を PG データ型に変換するために、固定長タイプの値をコピーし、可変長タイプはポインタ参照として PG datum に直接変換します。
バッチスキャン: 列に対してバッチスキャンを使用します。行ごとのアクセスではなく、まず 1 つの列をスキャンし、次に次の列をスキャンするため、CPU キャッシュによりフレンドリーです。
シーク読み取りをサポート: ヒット時のフィルタリングジャンプに便利です。
6. ローカルキャッシュ
DADI は 2 つの機能を実現します。1 つは効率的なキャッシュ管理、もう 1 つは統一ストレージアクセスです。DADI を知る前に、RT とスループットの 2 つの次元から DADI とオープンソースソリューションの比較テストをまず確認できます:
オープンソースソリューション alluxio と比較して、DADI はメモリヒットシーンの RT で桁違いの向上があり、スループットでも明らかな優位性があります。ディスクヒットのシナリオでも明らかなパフォーマンス優位性があります。一部の分析シナリオでは、ファイル統計情報を頻繁にしかし少量で読み取るため、これらの統計情報をローカルにキャッシュします。この優位性は全体のパフォーマンスで大きな向上をもたらします。
キャッシュヒットシナリオにおける DADI のパフォーマンス優位性については、以下のアーキテクチャを参照できます:
DADI SDK: 標準的な読み書きインターフェースを通じてストレージにアクセスし、キャッシュがヒットするかに応じてショートサーキットリード(ショートサーキットリード)または IPC プロセス通信でローカル DADI Service にアクセス、またはリモート DADI Service にアクセスします。分散キャッシュサービスに対応し、ライブラリとして ADB PG の読み書きプロセスに組み込まれています。
キャッシュインスタンス: ローカルキャッシュを管理し、キャッシュファイルは仮想ブロックデバイスとして抽象化されてアクセスされます。メモリ内のデータとディスクの現在のホット/コールドがブロック単位で管理されます。
ここでの核心設計は:
ショートサーキットリード: 共有メモリを直接読み取り、IPC を通じた読み取りを回避します。
キャッシュがヒットするかどうかのデータ構造も共有メモリ内にあります。参照カウントと robust mutex の組み合わせにより、共有メモリデータのマルチスレッドセーフを確保します。
ディスク読み取りは 100us で、+ 27us はほぼディスク読み取り自体の RT に等しく、IPC は shm 通信を使用し、ローカルソケット通信は使用しません。
極めて低いリソース使用量。
メモリ: DADI Service が使用するメモリは 100〜200M の間です。理由は、共有メモリに基づく IPC 実装、ハッシュテーブルなどのデータ構造により、マルチプロセスアーキテクチャ下でのメモリ膨張を回避し、ストリームライン化されたエンコーディング方式、16k のメモリページが 4byte の管理構造に対応するためです。
CPU: ローカル DADI Service のディスクが満杯の時、シングルコア CPU は約 20% を使用します。CPU は SDK 側で使用され、SDK はローカル DADI Service とほとんど通信しません。
さらに、DADI のメモリヒット時の優位性をよりよく活用するために、行列混合ストレージと組み合わせて以下の最適化を行いました:
キャッシュ優先度: 統計情報の高優先度をサポートし、メモリに常駐、インデックス情報はローカルディスクに常駐。ディメンションテーブルデータのローカル高優先度キャッシュをサポート。
きめ細かいキャッシュ戦略: 大きなテーブルのコールドデータアクセスにより、ローカルのすべてのホットデータが置き換えられるのを避けるため、大きなテーブルは専用キャッシュエリアを使用します。
ファイル非同期プリフェッチ: クエリ状況に基づいて、解析されたデータファイルをローカルに事前読み取りします。このプロセスは現在のファイルの読み書きに影響せず、非同期です。
7. ベクトル化実行
ADB PG クラウドネイティブバージョンはベクトル化実行エンジンもサポートしています。核心はバッチの蓄積により CPU キャッシュ内のデータヒット率を高め、コード生成により関数呼び出し回数を削減し、複雑な計算命令のジャンプを削減し、SIMD 命令により計算を加速することです。メモリプール管理によりオペレータ間のメモリコピーを削減します。詳細は [3] を参照してください。
8. 順序感知
データの順序は主に 2 つの側面で使用されます。1 つは順序付けられた IO クリッピング、もう 1 つは計算プロセスでのソーティングを最小限に抑えることです。IO クリッピングは行列混合で多くの議論があるため、ここでは主に 2 番目のポイントについて議論します。ここでの主な作業は:
冗長なソート操作の排除。データ自体が順序付けられており、ソーティング要件を満たしている場合、ソート操作を追加する必要はありません。
ソートが必要な列を最小限に抑えます。たとえば、{c1,c2,..cn} をソートしたい場合、述語 c1=5 がある場合、順序は {c2,..cn} に簡略化され、ソーティングのための 1 つのフィールドを回避します。
順序のプッシュダウン。初期化フェーズで、降順意図のソーティング操作を可能な限りプッシュダウンします。
以下の方法を使用してソートスキャンオペレータを生成します。SQL をクエリして AST を生成するために解析した後、一連のヒューリスティックルールに従って変換を行い、物理実行計画を生成します:
まず、(join/group by/distinct/order by) などの異なるオペレータの順序要件に従って、オペレータの興味深い順序(つまり、このオペレータが期待する順序付き入力)を確立します。
次に、ソートスキャンプロセスで生成される興味深い順序は、可能な限り下位のオペレータにプッシュダウンされ(事前ソート)、順序属性要件にできるだけ早く適合します。
オペレータに複数の興味深い順序がある場合、それらをマージして、1 つのソートで複数の順序属性の要件を満たすようにします。
さらに、ソートスキャンオペレータの実装があります。ストレージ層はファイルの厳密な順序とおおまかな順序のみを保証できます。マルチウェイマージアルゴリズムを使用してこれを実現します。
ここでの問題は、ソートスキャンのマルチウェイマージはデータを 1 つずつ読み取る必要があることで、ベクトル化バッチスキャンとファイルのバッチ読み取りと矛盾することです。CBO を使用して最適実行計画を選択します。
9. きめ細かい並列処理
ADB PG は MPP アーキテクチャであり、ノード間の並列計算機能を十分に発揮できます。クラウドネイティブバージョンはデータをバケットに分割するため、ノード内できめ細かい並列処理を実現できます。join を例にとって説明します:
左側はノード内で並列 join なしの実行計画です。2 つのプロセスが起動され、1 つは hash join の build 用、もう 1 つは probe 用です。たとえば、上記の図の各バケットのデータを並列に計算できます。データはバケットに従って分割されているため、join キーが分散されている場合、ノード内の並列性もローカル join の最適化を完璧にヒットします。
4. パフォーマンス結果
1. スケーラビリティパフォーマンス
2. 読み書きパフォーマンス
パフォーマンスをテストするために、4*4C 仕様のインスタンスを使用し、ADB PG の新しいクラウドネイティブバージョンとストレージ弾性バージョンのパフォーマンス比較テストを実施しました。
書き込みパフォーマンステスト
テストテーブルは scale factor = 500 の TPC-H lineitem テーブルを使用します。異なる同時実行数で copy コマンドを同時に実行し、コマンド実行時間を測定し、総データ量を実行時間で割ってスループットを取得します。
単一同時実行性では、新バージョンのパフォーマンスはストレージ弾性バージョンと類似しています。主にリソースがフル稼働していないためです。
4 同時実行性では、新バージョンのスループットはストレージ弾性の 2 倍です。理由は lineitem テーブルにソートキーが定義されており、新バージョンはデータ書き込み時に WAL ログを書き込む必要がなく、バッチングとパイプライン並列処理が弾性ストレージバージョンより高速であり、さらにマージ時に追加の WAL を書き込む必要があるため、一定の優位性があります。
8 同時実行性では、新バージョンは 4 同時実行性とほぼ同じです。主に 4C 4 同時実行性で既に CPU を使い切っているため、同時実行性を増やしても改善されないためです。
読み取りパフォーマンステスト
読み取りパフォーマンスを包括的にテストするために、3 つのシナリオをテストしました:
フルメモリ: TPCH sf が 10 のデータセットが使用され、10G のテストデータセットが生成されます。
フルローカルディスクキャッシュ: TPCH sf が 500 のデータセットが使用され、500GB のテストデータセットが生成されます。
半分キャッシュ、半分 OSS: TPCH sf が 2000 のデータセットが使用され、2000GB のテストデータセットが生成されます。(ローカルディスクキャッシュ 960GB)
テスト結果は以下の通りです(縦軸は ms 単位の RT)
フルメモリ
フルローカルディスクキャッシュ
半分ローカルキャッシュ、半分 OSS
上記のテスト結果から:
クラウドネイティブバージョンは、古い弾性ストレージバージョンと比較してパフォーマンスが 2 倍以上向上しています。きめ細かい並列処理による加速効果のためです。
TPCH などのコンピューティング集約型ジョブでは、データの半分がキャッシュされていても、半分 OSS のパフォーマンスは良好です。sf 2000 のデータ量は sf 500 の 4 倍で、rt は 2.8 倍に増加しています。OSS への帯域幅ボトルネックがありますが、読み取り自体のプリフェッチなどの最適化によるものです。
5. まとめ
AnalyticDB PostgreSQL の新しいクラウドネイティブバージョンは、物理リソースを完全にプールし、ストレージとコンピューティング機能を単位で割り当て、柔軟なデプロイメントを実装します。この機能はユーザーに究極のコスト効率を提供し、コンピューティングパワーの最適分布を実現し、ユーザーの使用敷居を下げ、ユーザーがビジネスに集中できるようにし、コンピューティングパワーとストレージの計画に多くのエネルギーを費やす必要をなくし、体験のアップグレードを実現します。
ストレージとコンピューティングの分離により、ユーザーはビジネス負荷モデルに従ってコンピューティング集約型またはストレージ集約型に容易に適応でき、使用に応じて保存および課金され、ストレージとコンピューティングの剛直な統合によるリソースの浪費を回避できます。
ビジネス負荷のピークと谷に動的に適応し、クラウドネイティブ MPP アーキテクチャのコンピューティング側はシェアードナッシングアーキテクチャを使用し、秒レベルの弾力的スケーリング機能をサポートし、共有ストレージにより基盤ストレージがコンピューティングから独立しています。これにより、ユーザーが初期段階で仕様を選択する敷居を下げ、後期段階でビジネスに応じて動的に調整する柔軟性を確保します。
ストレージとコンピューティングの分離に基づき、データ共有機能を提供し、物理マシンの境界を真に打ち破り、クラウド上のデータを真に流通させます。たとえば、インスタンス間のデータのリアルタイム共有は、1 つのストレージと複数の読み取りの使用モードをサポートし、従来のデータウェアハウスインスタンス間のデータアクセスが最初にインポートしてからアクセスする必要があるという孤立した島を打ち破り、操作を簡略化し、効率を向上し、コストを削減します。
6. 今後の計画
上記のストレージ分離アーキテクチャに基づき、主に 3 つの方向があります:
機能の完成。この部分は主に、プライマリキー、インデックス、マテリアライズドビュー、書き込みの完成など、現バージョンの制限事項を完成させるものです。
パフォーマンスの継続的最適化。主にキャッシュがヒットしないシーンの最適化です。
クラウドネイティブアーキテクチャの継続的アップグレード。主に現在のストレージとコンピューティングの分離アーキテクチャ下でのユーザー体験のさらなる向上です。
クラウドネイティブアップグレードでは、主に 2 つの重要な方向があります:
ストレージと計算の分離は、サーバーレスに向けたさらなる一歩であり、スケーリングの感覚がありません。メタデータと状態はコンピューティングノードからサービス層にさらに剥离され、セグメントはステートレスになります。これの利点は、スケーリングでユーザーに無関心を感じさせられることです。もう 1 つの利点は、ステートレスなセグメントがシステムの高可用性の向上に有利なことです。現在、アクティブスタンバイモードを通じて高可用性を提供していますが、ノード障害がある場合、アクティブスタンバイ切り替えのキャッシュ失敗パフォーマンスは急激に低下します。セグメントがステートレスになった後、直接クラスターから削除し、「縮小」方法を使用してサービスを継続的に改善します。
インスタンス間のアプリケーションデータ共有。さらに、分析ビジネスの場合、データ規模は TB 単位から始まり、従来のデータウェアハウスは煙突アーキテクチャを採用し、データの冗長性があり、データ同期コストが高くなります。インスタンス間のデータ共有機能を提供し、データウェアハウスアーキテクチャを再構築したいと考えています。
Garner の予測によると、2022 年までに全データベースの 75% がクラウドプラットフォームにデプロイまたは移行されます。もう一つの権威ある機関である IDC も、2025 年までにデータベースの 50% 以上がパブリッククラウドにデプロイされ、中国は驚くべき 70% 以上に達すると予測しています。長年の発展を経て、クラウドデータベースは Cloud-Hosted(クラウドホスティング)から Cloud Native(クラウドネイティブ)モデルへと変革を遂げました。
Cloud-Hosted: 市場および業界のクラウド要件に基づき、ほとんどのベンダーはクラウドホスティングを進化の第一歩として選択しています。このモデルでは、ユーザーがオフラインで独自の IDC を構築する必要がなくなり、クラウドプロバイダーの標準化されたリソースに依存してデータウェアハウスを移行し、高度なホスティングを提供することで、ユーザーを基盤ハードウェアの管理コストや Lingplan リソースの制約から解放します。
Cloud-Native: しかし、より多くのビジネスがクラウドに移行されるにつれ、基盤のコンピューティングリソースとストレージリソースが一体化されているため、ユーザーは使用時にリソースの不要な浪費を考慮する必要が生じます。たとえば、コンピューティングリソースの増加はストレージの関連増加を必要とし、無効なコストが発生します。ユーザーはクラウドリソースがよりきめ細かい方法でデータウェアハウスリソースを分解できることを期待し始めます。つまり、コンピューティング機能とストレージ機能を分離し、ビジネスのリソースオーケストレーションを満たすために販売可能な単位に分割することです。この時点で、クラウドネイティブの最大の価値が真に発揮されます。ストレージと計算のバランスが取れたデータウェアハウスの構築に注力するのではなく、ユーザービジネスに向き合い、大規模なコンピューティングまたはストレージの傾斜を可能にし、ビジネスに必要なリソースを独立してデプロイします。最小単位でデプロイおよび販売します。この瞬間、真にデータウェアハウスのクラウドネイティブ時代に入ったと言えます。
2021 年の雲栖大会で、Alibaba Cloud は新しいクラウドネイティブアーキテクチャのデータウェアハウスを発表しました [1]。本記事では、クラウドネイティブデータウェアハウスプロダクト AnalyticDB PostgreSQL(以下 ADB PG と称する)の Cloud-Hosted から Cloud-Native への進化と探求を紹介し、真のリソースプーリングと柔軟な販売を実現するための基盤設計と考え方を議論します。アーキテクチャ設計、主要技術、パフォーマンス結果、効果実現、および今後の計画を含みます。(全文の読了時間は約 10 分です)
2. ADB PG クラウドネイティブアーキテクチャ
ユーザーがクラウドデータウェアハウスに迅速に適応できるように、現在クラウド上で MPP アーキテクチャの設計コンセプトを採用し、コーディネーションノードとコンピューティングノードを独立してデプロイしていますが、単一の ECS 上にそれらを載せ、コンピューティングノードのストレージとコンピューティングの統合デプロイメント設計を実現しています。この設計アーキテクチャはクライアント側で高度に適応可能でセルフビルドされており、データウェアハウスビジネスをクラウドに迅速かつ非破壊的に移行できるため、初期のクラウド適応に非常にフレンドリーで、リソースの並列拡張という主要要件を満たしています。
クラウドネイティブのさらなる進化に伴い、全新的なストレージとコンピューティングの分離アーキテクチャを提供し、プロダクトをサービス層、コンピューティング層、および共有ストレージ層にさらに分割しました。アーキテクチャ図は以下の通りです:
マスターコーディネーションノード: グローバルスキーマ情報を保存し、グローバルトランザクション管理を実現します。
行ストレージエンジン: メタデータ情報を保存するために使用され、メタデータ情報は主に共有ストレージファイルの可視性情報を指し、2 つの部分を含みます:
1 つはファイルとテーブルの関係です
もう 1 つは削除されたデータの削除ビットマップです
行ストレージに基づいて、PG のローカルトランザクション機能を継承でき、追加・削除・更新・参照の際に PG のトランザクション機能と完全に互換性があります。
ローカルキャッシュ: ストレージチームの DADI を導入することで高性能なローカルキャッシュを実現します。DADI の正式名称は Alibaba Cloud Data Accelerator for Disaggregated Infrastructure です。オープンソースプロダクトと比較して、パフォーマンスは桁違いに向上しています。
共有ストレージ: ClickHouse からいくつかの重要な設計を借用し、ストレージ層で MergeTree ベースの行列混合ストレージを実装しました。さらに、ファイルインターフェースに基づいた統一アクセスインターフェースを作成し、OSS と HDFS の両方と高度に互換性のある様々な形式の分散ファイルシステムに対応しています。
アーキテクチャを設計する際、同じく Greenplum から派生した HAWQ と比較すると、HAWQ はメタデータをマスターに保存します。書き込みのたびに、変更されたメタデータをマスターに持って更新します。読み取り時はマスターから必要なメタデータを読み取り、すべてのメタデータを実行計画に含めることで、セグメントが対応するメタデータを取得でき、セグメントを完全にステートレスにできます。
しかし、この設計には 2 つの核心的な問題が生じます:
メタデータの膨張により、マスターがボトルネックになる。
メタデータのパフォーマンスに制限され、高い同時実行性のリアルタイム書き込みをサポートできない。
このように設計しなかった理由は、将来的に高い同時実行性タスクをサポートしたいからです。ADB PG は 2 年以上かけて Greenplum の単一ポイントマスターアーキテクチャをマルチマスターに拡張しました。核心は高い同時実行性タスクのリアルタイム書き込み問題を解決することです。メタデータがマスターに保存されていると、以下のような問題が発生します:
マスター上のメタデータのストレージとアクセスが単一ポイントのボトルネックを形成しやすい
ADB PG の実行層でメタデータを実行計画に組み込むための大規模なリファクタリングが必要であり、クエリプラン自体の帯域幅が劇的に増加するため、高い同時実行性を持つ小規模クエリに非常に不利です。
そこでアーキテクチャを改善し、メタデータをセグメントに分散することで、以下を実現しました:
マスターのストレージと読み書きがボトルネックにならない
実行層のリファクタリングが不要で、メタデータを分散することで単一のクエリの帯域幅圧力を軽減
メタデータをセグメント上の分散 KV に配置し、スケールアウト/スケールイン時のメタデータ再配置の問題を解決
共有ストレージに OSS を使用する理由は、単一ユーザーのビジネスデータが継続的に増加するにつれ、持続可能なストレージソリューションが必要であり、OSS の低ストレージコスト、高可用性、データの永続性が最適な選択だからです。
OSS を使用するもう 1 つの利点は、オンデマンドで課金されることです。ユーザーはストレージスペースのサイズを事前に設定する必要がなく、保存されているデータ量に応じて課金されます。データが削除されると課金されません。ESSD クラウドディスクは通常データに基づいてストレージ水位を計算する必要があり、ストレージリソースの真のオンデマンド供給を行うことができず、容量の自動縮小もできません。これらすべてがクラウドネイティブの設計思想に反します。しかし同時に、OSS の欠点は RT です:
OSS の RT 問題を解決するために、コンピューティングノードに一定割合のローカルディスクを設定し、アクセス高速化を図っています。さらに、ClickHouse の MergeTree ストレージの核心思想を参考にした高性能な行列混合ストレージを設計しました。順序を核心とし、ファイルは絶対的に順序付けされ、ファイル内は相対的に順序付けされています。マージの非同期操作により、ファイルのマージとソートを実現し、順序付けに基づいてファイル内に 3 層の統計情報を設計し、大量の IO クリッピング最適化を行いました。
以下、各技術ポイントをさらに詳しく紹介します。
3. 主要技術
1. 弾力的スケーリング
高速な弾力的スケーリングを実現するために、私たちの方法は共有ストレージ上でデータをハッシュバケットで整理することです。スケーリング後、コンピューティングノードとバケットをコンシステントハッシュで再マッピングします。バケットとセグメントの割り当ての均一性を解決し、スケーリング後のキャッシュ失敗の影響を低減するために、従来のコンシステントハッシュアルゴリズムを改善し、スケーリング中の動的マッピングをサポートしました。
データをハッシュバケットに従って複数のシャードに分割し、オブジェクトストレージ上のデータをシャーディング粒度で再マッピングします。コンピューティングノードの拡張がシャード数を超えた場合、データを再配布する必要があります。この問題を解決するために、バックグラウンドでハッシュバケットの分割とマージをサポートし、データの再配布を回避します。
以上がスケーリング時の「データ」の再マッピングであり、データファイルの可視性を記述するメタデータは行テーブルに保存されます。Greenplum のデータ再配布戦略を引き続き使用していますが、メタデータの再配布を高速化するために、並列配布などの最適化を行っています。
容量拡張を例にとって、容量拡張のプロセスをさらに詳しく説明します:
ECS リソースプーリング、ネットワークカードの並列ロード、Docker イメージの予熱などの技術と組み合わせ、16 ノード以内のエンドツーエンドの所要時間は約 1 分です。
2. 階層ストレージ
階層ストレージの実装は以下の通りです:
上記の図に示すように、ストレージリソースをメモリ、ローカルディスク、共有ストレージの 3 層に分割します。
メモリ: 主に行ストレージアクセスの高速化とファイル統計情報のキャッシュを担当します。
ローカルディスク: 行ストレージの永続ストレージとして、およびリモート共有ストレージのローカルアクセラレータとして使用します。
リモート共有ストレージ: データの永続ストレージとして使用します。
3. 読み書きプロセス
書き込みプロセスは以下の通りです:
ユーザーが書き込んだデータは、データバッチングを通じて OSS に直接書き込まれ、同時にローカルディスクにメタデータが記録されます。このメタデータはファイルとデータテーブルの対応関係を記録します。メタデータは PG の行ストレージテーブルを使用して実装され、ファイルメタデータテーブルを通じてこの情報を保存します。
更新または削除時、OSS 上のデータを直接変更する必要はありません。削除マークを付けることで対応します。削除マークの情報もローカル行ストレージテーブルに保存され、可視性ビットマップを通じてこの情報を保存します。削除マークは読み取りパフォーマンスの低下を招くため、バックグラウンドマージを使用して削除情報をファイルに適用し、読み取りパフォーマンスへの影響を低減します。
書き込み時、セグメント上のデータをバケットに従ってさらに分割し、これにより小さなファイルの問題が発生します。小さなファイルの問題を解決するために、以下の最適化を行いました:
グループフラッシュ: 書き込みデータのバッチをグループフラッシュを通じて同じ OSS ファイルに書き込めます。OSS ファイルは ORC フォーマットを採用し、異なるバケットは対応するストライプに書き込まれます。
パイプラインの非同期並列処理: エンコーディングとソーティングは典型的な CPU 集約型タスクであり、OSS へのアップロードは典型的なネットワーク IO 集約型タスクです。これらの 2 種類のタスクを並列化し、OSS アップロードタスクを非同期タスクとして実行します。同時に次のバッチのデータのエンコーディングとソーティングを行い、書き込みパフォーマンスを高速化します。
リモート永続ストレージは 12 個の 9 の永続性を提供するため、メタデータを保存する行ストレージのみが WAL ログとダブルコピーで信頼性を確保します。データ自体は WAL ログと複数コピーなしで共有ストレージに書き込まれます。WAL ログの削減、WAL ログのマスター・スレーブ同期の削減、および非同期並列処理とバッチ蓄積により、バッチ書き込みシナリオでは、書き込みパフォーマンスは基本的に ECS 弾性ストレージバージョンと同等です。
読み取りプロセスは以下の通りです:
ファイルメタデータテーブルを読み取ることで、スキャン対象の OSS ファイルを取得します。
OSS ファイルに従って対応するファイルを読み取ります。
読み取ったファイルは、メタデータテーブルの可視性ビットマップを通じて削除されたデータをフィルタリングします。
OSS 読み取りによる遅延を解決するために、DADI も導入し、キャッシュ管理の実装と共有ファイルアクセスのカプセル化を支援しています。ファイル読み取り時にまずローカルキャッシュの有無を判断し、あればローカルディスクから直接読み取ります。なければ OSS に読み取りに行き、読み取り後にローカルにキャッシュされます。書き込み時は OSS に直接書き込み、ローカルディスクにライトバックします。ライトバックは非同期操作です。DADI を通じてローカルキャッシュデータの淘汰も管理しており、LRU/LFU 戦略に従ってコールドデータを自動的に淘汰します。
トランザクションは PG の行ストレージを使用して実装されているため、ADB PG のトランザクションと完全に互換性があります。問題は、スケーリング時にこの部分のデータを再配布する必要があることです。このデータの再配布メカニズムを再設計し、事前パーティショニング、並列コピー、ポイントツーポイントコピーなどの技術を通じて、スケーリング時間を大幅に短縮しました。
パフォーマンス最適化ポイントをまとめると:
ローカル行ストレージテーブルを通じてトランザクション ACID を実現し、データブロックレベルの同時実行性をサポート。
バッチとパイプラインの並列化により書き込みスループットを向上。
DADI に基づくメモリとローカル SSD のマルチレベルキャッシュによるアクセス高速化。
4. 可視性テーブル
共有ストレージファイルに関連する情報をファイルメタデータに保存します。その構造は以下の通りです:
ハッシュバケット: スケーリング時のデータ再配置時にバケットに従ってスキャンするために使用されます。クエリ時にもバケットに従ってバケットごとに処理されます。
レベル: マージツリーのレベルです。レベル 0 はリアルタイムに書き込まれたデータを表し、この部分のデータはマージ時に高い重みを持ちます。
物理ファイル ID: ファイルに対応する ID です。64 バイトで、セグメントとの関連がなくなり、セグメント内のテーブルの一意性を保証するだけでなく、グローバルに一意である必要があります。
ストライプ ID: 1 つの OSS ファイルに複数のバケットファイルを含めることができるため、ストライプを単位として、セグメントで書き込まれた複数のバケットを 1 つの OSS ファイルにマージするのに便利です。小さな OSS ファイルによるパフォーマンス低下や、小さな OSS ファイルの爆発を回避します。
合計カウント: ファイルの行数で、バックグラウンドマージの重みでもあります。大きいほどマージ重みが低くなります。
可視性ビットマップは削除されたファイル情報を記録します。
Start_row は 32k に対応し、削除ビットマップに対応します。この 32000 4k で、行ストレージが使用する 32k ページは 7 つのレコードを保存できます。
Delete count は削除された数です。
OSS にアクセスする必要なく、マージが必要なファイルを直接取得でき、OSS へのアクセスによる遅延を回避します。OSS もスループットに制限があるため、頻繁なアクセスによる OSS のフロー制限のトリガーを回避できます。
5. 行列混合ストレージ
MergeTree の構造は上記の図の左側に示されています。核心はバックグラウンドマージ方式で小さなファイルを大きな順序付きファイルにマージすることであり、マージ時にデータを再配置できます。たとえば、データの順序特性を変更してさらなる最適化を行います。順序感知最適化については後述を参照してください。leveldb との違いは:
レイヤー 0 のリアルタイム書き込みはマージされ、異なるバケットのファイルは大きなファイルにマージされ、異なるバケットは対応するストライプに落ちます。
マージはレイヤーをまたいでマージ条件を満たすファイルをマージします。ファイルは厳密に順序付けられていますが、ファイル間はおおまかに順序付けられています。レイヤー数が高いほどファイルは大きくなり、ファイル間の重複は小さくなります。
各ファイルに行列混合ストレージフォーマットを使用しており、行列混合ストレージの具体的なストレージフォーマットは右側にあります。ORC 基礎上で多くの最適化を行いました。
ORC ファイル: 1 つの ORC ファイルに複数のストライプを含めることができ、各ストライプには複数の行グループが含まれ、各行グループには固定レコードが含まれ、これらのレコードは列ごとに独立して保存されます。
PostScript: ファイルの説明情報 PostScript、ファイルメタ情報(ファイル全体の統計情報、データディクショナリなどを含む)、すべてのストライプ情報、およびファイルスキーマ情報を含みます。
ストライプ: ストライプは行の分割で、行をグループ化してストライプを形成し、読み取りファイルは行グループ単位で行われ、各列のインデックスとデータを保存します。インデックスデータ、行データ、およびストライプフッターで構成されます。
ファイルフッター: ストライプの位置、ストライプ内の各列の統計情報、およびすべてのストリームタイプと位置を保存します。
インデックスデータ: 行グループレベルの統計情報を保存します。
データストリーム: ストリームはファイル内の有効なデータピースを表し、インデックスとデータを含みます。
インデックスストリームは各行グループの位置と統計情報を保存します。データストリームは複数のタイプのデータを含み、具体的なタイプは列タイプとエンコーディング方式によって決まります。以下、整数と文字列の 2 つのタイプを例として示します:
整数フィールドの場合、ビットストリームと整数ストリームの両方が使用されます。ビットストリームは特定の値が null かどうかを識別するために使用され、整数ストリームは整数フィールドの null でないレコードの整数値を保存するために使用されます。
文字列タイプフィールドの場合、ORC ライターはフィールド値の異なるコンテンツ数が null でないレコードの総数の 80% 以下であるかどうかをチェックし、辞書エンコーディングを使用します。フィールド値はビットストリーム、バイトストリーム、および 2 つの整数ストリームに保存されます。ビットストリームは null 値の識別にも使用され、バイトストリームは辞書値の保存に使用され、1 つの整数ストリームは辞書の各エントリの長さを保存し、もう 1 つの整数ストリームはフィールド値を記録するために使用されます。辞書エンコーディングを使用できない場合、ORC ライターはこのフィールドの繰り返し値が少なすぎて辞書エンコーディングの効率が低いことを認識します。ORC ライターはバイトストリームを使用して String フィールドの値を保存し、整数ストリームを使用して各フィールドのバイト長を保存します。
ORC ファイルには 3 層の統計情報が保存されており、それぞれファイルレベル、ストライプレベル、行グループレベルです。ストレージパフォーマンス向上の核心は IO を削減することです。ORC の統計情報とインデックスに基づいて様々なプッシュダウンを実装し、IO クリッピングを実現しています。たとえば、Projection プッシュダウンでは、マテリアライズが必要な列のみをスキャンします。Agg プッシュダウンでは、必要な min、max、sum、unique を統計情報またはインデックスから直接読み取って返します。データストリームの解凍を回避します。述語についても、フィルタのプッシュダウンをサポートし、統計情報を通じて直接フィルタリングし、条件を満たさないストライプを直接スキップします。様々な演算子、in/not in、および式の等価変換をサポートしています。
さらに、ストレージフォーマットのパフォーマンスを以下のように最適化しました:
ゼロコピー: ORC データ型を PG データ型に変換するために、固定長タイプの値をコピーし、可変長タイプはポインタ参照として PG datum に直接変換します。
バッチスキャン: 列に対してバッチスキャンを使用します。行ごとのアクセスではなく、まず 1 つの列をスキャンし、次に次の列をスキャンするため、CPU キャッシュによりフレンドリーです。
シーク読み取りをサポート: ヒット時のフィルタリングジャンプに便利です。
6. ローカルキャッシュ
DADI は 2 つの機能を実現します。1 つは効率的なキャッシュ管理、もう 1 つは統一ストレージアクセスです。DADI を知る前に、RT とスループットの 2 つの次元から DADI とオープンソースソリューションの比較テストをまず確認できます:
オープンソースソリューション alluxio と比較して、DADI はメモリヒットシーンの RT で桁違いの向上があり、スループットでも明らかな優位性があります。ディスクヒットのシナリオでも明らかなパフォーマンス優位性があります。一部の分析シナリオでは、ファイル統計情報を頻繁にしかし少量で読み取るため、これらの統計情報をローカルにキャッシュします。この優位性は全体のパフォーマンスで大きな向上をもたらします。
キャッシュヒットシナリオにおける DADI のパフォーマンス優位性については、以下のアーキテクチャを参照できます:
DADI SDK: 標準的な読み書きインターフェースを通じてストレージにアクセスし、キャッシュがヒットするかに応じてショートサーキットリード(ショートサーキットリード)または IPC プロセス通信でローカル DADI Service にアクセス、またはリモート DADI Service にアクセスします。分散キャッシュサービスに対応し、ライブラリとして ADB PG の読み書きプロセスに組み込まれています。
キャッシュインスタンス: ローカルキャッシュを管理し、キャッシュファイルは仮想ブロックデバイスとして抽象化されてアクセスされます。メモリ内のデータとディスクの現在のホット/コールドがブロック単位で管理されます。
ここでの核心設計は:
ショートサーキットリード: 共有メモリを直接読み取り、IPC を通じた読み取りを回避します。
キャッシュがヒットするかどうかのデータ構造も共有メモリ内にあります。参照カウントと robust mutex の組み合わせにより、共有メモリデータのマルチスレッドセーフを確保します。
ディスク読み取りは 100us で、+ 27us はほぼディスク読み取り自体の RT に等しく、IPC は shm 通信を使用し、ローカルソケット通信は使用しません。
極めて低いリソース使用量。
メモリ: DADI Service が使用するメモリは 100〜200M の間です。理由は、共有メモリに基づく IPC 実装、ハッシュテーブルなどのデータ構造により、マルチプロセスアーキテクチャ下でのメモリ膨張を回避し、ストリームライン化されたエンコーディング方式、16k のメモリページが 4byte の管理構造に対応するためです。
CPU: ローカル DADI Service のディスクが満杯の時、シングルコア CPU は約 20% を使用します。CPU は SDK 側で使用され、SDK はローカル DADI Service とほとんど通信しません。
さらに、DADI のメモリヒット時の優位性をよりよく活用するために、行列混合ストレージと組み合わせて以下の最適化を行いました:
キャッシュ優先度: 統計情報の高優先度をサポートし、メモリに常駐、インデックス情報はローカルディスクに常駐。ディメンションテーブルデータのローカル高優先度キャッシュをサポート。
きめ細かいキャッシュ戦略: 大きなテーブルのコールドデータアクセスにより、ローカルのすべてのホットデータが置き換えられるのを避けるため、大きなテーブルは専用キャッシュエリアを使用します。
ファイル非同期プリフェッチ: クエリ状況に基づいて、解析されたデータファイルをローカルに事前読み取りします。このプロセスは現在のファイルの読み書きに影響せず、非同期です。
7. ベクトル化実行
ADB PG クラウドネイティブバージョンはベクトル化実行エンジンもサポートしています。核心はバッチの蓄積により CPU キャッシュ内のデータヒット率を高め、コード生成により関数呼び出し回数を削減し、複雑な計算命令のジャンプを削減し、SIMD 命令により計算を加速することです。メモリプール管理によりオペレータ間のメモリコピーを削減します。詳細は [3] を参照してください。
8. 順序感知
データの順序は主に 2 つの側面で使用されます。1 つは順序付けられた IO クリッピング、もう 1 つは計算プロセスでのソーティングを最小限に抑えることです。IO クリッピングは行列混合で多くの議論があるため、ここでは主に 2 番目のポイントについて議論します。ここでの主な作業は:
冗長なソート操作の排除。データ自体が順序付けられており、ソーティング要件を満たしている場合、ソート操作を追加する必要はありません。
ソートが必要な列を最小限に抑えます。たとえば、{c1,c2,..cn} をソートしたい場合、述語 c1=5 がある場合、順序は {c2,..cn} に簡略化され、ソーティングのための 1 つのフィールドを回避します。
順序のプッシュダウン。初期化フェーズで、降順意図のソーティング操作を可能な限りプッシュダウンします。
以下の方法を使用してソートスキャンオペレータを生成します。SQL をクエリして AST を生成するために解析した後、一連のヒューリスティックルールに従って変換を行い、物理実行計画を生成します:
まず、(join/group by/distinct/order by) などの異なるオペレータの順序要件に従って、オペレータの興味深い順序(つまり、このオペレータが期待する順序付き入力)を確立します。
次に、ソートスキャンプロセスで生成される興味深い順序は、可能な限り下位のオペレータにプッシュダウンされ(事前ソート)、順序属性要件にできるだけ早く適合します。
オペレータに複数の興味深い順序がある場合、それらをマージして、1 つのソートで複数の順序属性の要件を満たすようにします。
さらに、ソートスキャンオペレータの実装があります。ストレージ層はファイルの厳密な順序とおおまかな順序のみを保証できます。マルチウェイマージアルゴリズムを使用してこれを実現します。
ここでの問題は、ソートスキャンのマルチウェイマージはデータを 1 つずつ読み取る必要があることで、ベクトル化バッチスキャンとファイルのバッチ読み取りと矛盾することです。CBO を使用して最適実行計画を選択します。
9. きめ細かい並列処理
ADB PG は MPP アーキテクチャであり、ノード間の並列計算機能を十分に発揮できます。クラウドネイティブバージョンはデータをバケットに分割するため、ノード内できめ細かい並列処理を実現できます。join を例にとって説明します:
左側はノード内で並列 join なしの実行計画です。2 つのプロセスが起動され、1 つは hash join の build 用、もう 1 つは probe 用です。たとえば、上記の図の各バケットのデータを並列に計算できます。データはバケットに従って分割されているため、join キーが分散されている場合、ノード内の並列性もローカル join の最適化を完璧にヒットします。
4. パフォーマンス結果
1. スケーラビリティパフォーマンス
2. 読み書きパフォーマンス
パフォーマンスをテストするために、4*4C 仕様のインスタンスを使用し、ADB PG の新しいクラウドネイティブバージョンとストレージ弾性バージョンのパフォーマンス比較テストを実施しました。
書き込みパフォーマンステスト
テストテーブルは scale factor = 500 の TPC-H lineitem テーブルを使用します。異なる同時実行数で copy コマンドを同時に実行し、コマンド実行時間を測定し、総データ量を実行時間で割ってスループットを取得します。
単一同時実行性では、新バージョンのパフォーマンスはストレージ弾性バージョンと類似しています。主にリソースがフル稼働していないためです。
4 同時実行性では、新バージョンのスループットはストレージ弾性の 2 倍です。理由は lineitem テーブルにソートキーが定義されており、新バージョンはデータ書き込み時に WAL ログを書き込む必要がなく、バッチングとパイプライン並列処理が弾性ストレージバージョンより高速であり、さらにマージ時に追加の WAL を書き込む必要があるため、一定の優位性があります。
8 同時実行性では、新バージョンは 4 同時実行性とほぼ同じです。主に 4C 4 同時実行性で既に CPU を使い切っているため、同時実行性を増やしても改善されないためです。
読み取りパフォーマンステスト
読み取りパフォーマンスを包括的にテストするために、3 つのシナリオをテストしました:
フルメモリ: TPCH sf が 10 のデータセットが使用され、10G のテストデータセットが生成されます。
フルローカルディスクキャッシュ: TPCH sf が 500 のデータセットが使用され、500GB のテストデータセットが生成されます。
半分キャッシュ、半分 OSS: TPCH sf が 2000 のデータセットが使用され、2000GB のテストデータセットが生成されます。(ローカルディスクキャッシュ 960GB)
テスト結果は以下の通りです(縦軸は ms 単位の RT)
フルメモリ
フルローカルディスクキャッシュ
半分ローカルキャッシュ、半分 OSS
上記のテスト結果から:
クラウドネイティブバージョンは、古い弾性ストレージバージョンと比較してパフォーマンスが 2 倍以上向上しています。きめ細かい並列処理による加速効果のためです。
TPCH などのコンピューティング集約型ジョブでは、データの半分がキャッシュされていても、半分 OSS のパフォーマンスは良好です。sf 2000 のデータ量は sf 500 の 4 倍で、rt は 2.8 倍に増加しています。OSS への帯域幅ボトルネックがありますが、読み取り自体のプリフェッチなどの最適化によるものです。
5. まとめ
AnalyticDB PostgreSQL の新しいクラウドネイティブバージョンは、物理リソースを完全にプールし、ストレージとコンピューティング機能を単位で割り当て、柔軟なデプロイメントを実装します。この機能はユーザーに究極のコスト効率を提供し、コンピューティングパワーの最適分布を実現し、ユーザーの使用敷居を下げ、ユーザーがビジネスに集中できるようにし、コンピューティングパワーとストレージの計画に多くのエネルギーを費やす必要をなくし、体験のアップグレードを実現します。
ストレージとコンピューティングの分離により、ユーザーはビジネス負荷モデルに従ってコンピューティング集約型またはストレージ集約型に容易に適応でき、使用に応じて保存および課金され、ストレージとコンピューティングの剛直な統合によるリソースの浪費を回避できます。
ビジネス負荷のピークと谷に動的に適応し、クラウドネイティブ MPP アーキテクチャのコンピューティング側はシェアードナッシングアーキテクチャを使用し、秒レベルの弾力的スケーリング機能をサポートし、共有ストレージにより基盤ストレージがコンピューティングから独立しています。これにより、ユーザーが初期段階で仕様を選択する敷居を下げ、後期段階でビジネスに応じて動的に調整する柔軟性を確保します。
ストレージとコンピューティングの分離に基づき、データ共有機能を提供し、物理マシンの境界を真に打ち破り、クラウド上のデータを真に流通させます。たとえば、インスタンス間のデータのリアルタイム共有は、1 つのストレージと複数の読み取りの使用モードをサポートし、従来のデータウェアハウスインスタンス間のデータアクセスが最初にインポートしてからアクセスする必要があるという孤立した島を打ち破り、操作を簡略化し、効率を向上し、コストを削減します。
6. 今後の計画
上記のストレージ分離アーキテクチャに基づき、主に 3 つの方向があります:
機能の完成。この部分は主に、プライマリキー、インデックス、マテリアライズドビュー、書き込みの完成など、現バージョンの制限事項を完成させるものです。
パフォーマンスの継続的最適化。主にキャッシュがヒットしないシーンの最適化です。
クラウドネイティブアーキテクチャの継続的アップグレード。主に現在のストレージとコンピューティングの分離アーキテクチャ下でのユーザー体験のさらなる向上です。
クラウドネイティブアップグレードでは、主に 2 つの重要な方向があります:
ストレージと計算の分離は、サーバーレスに向けたさらなる一歩であり、スケーリングの感覚がありません。メタデータと状態はコンピューティングノードからサービス層にさらに剥离され、セグメントはステートレスになります。これの利点は、スケーリングでユーザーに無関心を感じさせられることです。もう 1 つの利点は、ステートレスなセグメントがシステムの高可用性の向上に有利なことです。現在、アクティブスタンバイモードを通じて高可用性を提供していますが、ノード障害がある場合、アクティブスタンバイ切り替えのキャッシュ失敗パフォーマンスは急激に低下します。セグメントがステートレスになった後、直接クラスターから削除し、「縮小」方法を使用してサービスを継続的に改善します。
インスタンス間のアプリケーションデータ共有。さらに、分析ビジネスの場合、データ規模は TB 単位から始まり、従来のデータウェアハウスは煙突アーキテクチャを採用し、データの冗長性があり、データ同期コストが高くなります。インスタンス間のデータ共有機能を提供し、データウェアハウスアーキテクチャを再構築したいと考えています。
Related Articles
-
A detailed explanation of Hadoop core architecture HDFS
Knowledge Base Team
-
What Does IOT Mean
Knowledge Base Team
-
6 Optional Technologies for Data Storage
Knowledge Base Team
-
What Is Blockchain Technology
Knowledge Base Team
Explore More Special Offers
-
Short Message Service(SMS) & Mail Service
50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00
