GreenplumでSQLクエリを最適化するための5つのライフハック



データベースに関連するプロセスは、遅かれ早かれ、このデータベースへのクエリのパフォーマンスに問題が発生します。

RostelecomのデータウェアハウスはGreenplum上に構築されており、ほとんどの計算(変換)はETLメカニズムを開始(または生成および開始)するSQLクエリによって実行されます。 DBMSには、パフォーマンスに大きく影響する独自のニュアンスがあります。 この記事は、パフォーマンスと共有経験の点でGreenplumを使用する上で最も重要な側面を強調する試みです。

Greenplumの概要
Greenplum- MPPデータベースサーバー。そのコアはPostgreSql上に構築されています。

PostgreSqlプロセスのいくつかの異なるインスタンス(インスタンス)を表します。 それらの1つはクライアントのエントリポイントであり、マスターインスタンス(マスター)と呼ばれ、残りはすべてセグメントインスタンス(セグメント、独立したインスタンス、それぞれ独自のデータを持っています)と呼ばれます。 各サーバー(セグメントホスト)は、1つから複数のサービス(セグメント)で実行できます。 これは、サーバーリソースと主にプロセッサをより活用するために行われます。 ウィザードはメタデータを保存し、クライアントをデータに接続する役割を果たします。また、セグメント間で作業を分配します。



詳細については、 公式ドキュメントを参照してください。

さらに記事では、リクエストプランへの多くの参照があります。 Greenplumの情報はこちらから入手できます

Greenplumで適切なクエリを作成する方法(まあ、少なくとも悲しくはない)


分散データベースを扱っているため、sqlクエリの記述方法だけでなく、データの格納方法も重​​要です。

1.配布


データは物理的に異なるセグメントに保存されます。 セグメントごとにランダムに、またはフィールドまたは一連のフィールドのハッシュ関数の値によってデータを分離できます。

構文(テーブルを作成する場合):

DISTRIBUTED BY (some_field) 

または:

 DISTRIBUTED RANDOMLY 

このようなフィールドを持つレコードは1つのセグメントに分散されるため、データのゆがみにつながる可能性があるため、分布フィールドは良好な選択性を持ち、null値を持たないようにする必要があります。

フィールドタイプは整数であることが好ましい。 このフィールドは、テーブルを結合するために使用されます。 ハッシュ結合は(クエリの実行に関して)テーブルを結合するための最良の方法の1つであり、このデータ型で最適に機能します。

配布には、2つ以下のフィールドを選択することをお勧めします。もちろん、1つは2つよりも優れています。 分散キーの追加フィールドは、まずハッシュのための追加時間を必要とし、次に(ほとんどの場合)結合の実行時にセグメント間のデータ転送を必要とします。

1つまたは2つの適切なフィールドを選択できない場合、および小さいラベルの場合は、ランダム分布を使用できます。 ただし、このような分布は、単一のレコードではなく、大量のデータ挿入に最適であることを考慮する必要があります。 GreenPlumは、 循環アルゴリズムに従ってデータを配布し、最初のセグメントから開始して、挿入操作ごとに新しいサイクルを開始します。これは、頻繁に小さな挿入を行うと、歪み(データスキュー)につながります。

適切に選択された分布フィールドを使用すると、他のセグメントにデータを送信せずに、すべての計算がセグメントで実行されます。 また、テーブルの最適な結合(結合)を行うには、同じ値を同じセグメントに配置する必要があります。

写真での配布
適切な配布キー:


不十分な配布キー:


ランダム分布:


結合で使用されるフィールドのタイプは、すべてのテーブルで同じでなければなりません。
重要:この場合、クエリ中の負荷も均等に分散されないため、クエリをフィルタリングするために使用されるものを分散フィールドとして使用しないでください。

2.パーティショニング


パーティション化により、 ファクトなどの大きなテーブルを論理的に分離された部分に分割できます。 Greenplumは、テーブルを物理的に個別のテーブルに分割します。各テーブルは、p。1の設定に基づいてセグメントに分割されます。

テーブルは論理的にセクションに分割する必要があります。そのためには、whereブロックでよく使用されるフィールドを選択します。 実際には、これが期間になります。 したがって、クエリでテーブルに適切にアクセスすると、大きなテーブル全体の一部のみを操作できます。

一般に、パーティション分割はかなりよく知られたトピックであり、パーティション分割と配布に同じフィールドを選択すべきではないことを強調したかったのです。 これにより、リクエストが1つのセグメントで完全に実行されることになります。

それでは、実際に要求に行きましょう。 要求は、特定の計画に従ってセグメントで実行されます。

3.オプティマイザー


Greenplumには、組み込みのレガシーオプティマイザーとサードパーティのOrcaオプティマイザーの2つのオプティマイザーがあります:GPORCA-Orca-Pivotal Query Optimizer。

リクエストに応じてGPORCAを有効にします。

 set optimizer = on; 

原則として、 GPORCAオプティマイザーは組み込みより優れています。 サブクエリとCTEでより適切に動作します(詳細はこちら )。
最大データフィルタリング(パーティションプルーニングを忘れないでください)と明示的に指定されたフィールドのリストを使用して、CTEの大きなテーブルを呼び出しました。非常にうまく機能します。

たとえば、クエリプランをわずかに変更します。そうしないと、スキャンされたパーティションが表示されます。

標準オプティマイザー:



オルカ:



GPORCAでは、パーティション/配布フィールドの更新もできます。 ただし、組み込みオプティマイザーのパフォーマンスが向上する場合があります。 サードパーティのオプティマイザーは統計を非常に要求します。 分析することを忘れないことが重要です。

オプティマイザーがどれほど優れていても、不適切に記述されたクエリはOrcaを拡張しません。

4. whereブロックまたは結合条件のフィールドを使用した操作


フィルターフィールドに適用される関数または結合の条件がレコードに適用されることを覚えておくことが重要です。

パーティションフィールドの場合(たとえば、パーティションフィールドのdate_trunc-日付)、この場合はGPORCAでさえ正しく動作できず、 パーティションのクリッピングは機能しません。

 --     set optimizer = on; explain select * from edw_ods.t_000045_bills c where date_trunc('month',tech_dt) between to_date('20180101', 'YYYYMMDD') and to_date('20180101', 'YYYYMMDD') + interval '1 month - 1 second' ; 



 --     set optimizer = on; explain select * from edw_ods.t_000045_bills c where tech_dt between to_date('20180101', 'YYYYMMDD') and to_date('20180101', 'YYYYMMDD') + interval '1 month - 1 second' 



また、パーティションの表示にも注意を向けています。 組み込みのオプティマイザーは、パーティションをリストに表示します:



同じパーティションフィルター内の定数に関数を慎重に適用します。 例は同じdate_truncです:

 date_trunc('month',to_date($p_some_dt, 'YYYYMMDD')) 



GPORCAはこのようなフェイントに完全に対処し、正常に動作しますが、標準オプティマイザーはもう対処しません。 ただし、明示的な型変換を行うことで、それを機能させることができます。

 date_trunc('month',to_date($p_some_dt, 'YYYYMMDD'))::timestamp without time zone 



そして、すべてが間違っている場合はどうなりますか?

5.モーション


クエリプランで観察できる別のタイプの操作は、モーションです。 そのため、セグメント間のデータの移動にマークを付けました。


ブロードキャストと再配布は非常に不利な操作です。 これらは、リクエストが実行されるたびに実行されます。 それらを避けることをお勧めします。 クエリプランでこのような点を見たので、分散キーに注意する価値があります。 また、個別の結合操作が動作の原因です。

このリストは完全なものではなく、主に著者の経験に基づいています。 当時、インターネット上で一度にすべてを見つけることができませんでした。 ここで、リクエストのパフォーマンスに影響を与える最も重要な要因を特定し、これが発生した理由と理由を理解しようとしました。

この記事は、ロステレコムのデータ管理チームによって作成されました

Source: https://habr.com/ru/post/J442758/


All Articles