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.モーション



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





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



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



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



All Articles