hdfs_fdwの機能的評価

2018年11月1日(木)
稲垣 毅

はじめに

前回はビッグデータ向けのFDWを紹介し、Hadoop(HDFS)用のFDWであるhdfs_fdwの概要と使い方のノウハウを解説してきました。今回と次回は、hdfs_fdwの実装を確認して機能的な評価を行うとともに、業務的な面からコストや性能を評価し、利用場面等を検討していきたいと思います。

PostgreSQLでのFDWの仕組み

PostgreSQLはFDWのインタフェースをC言語の関数インタフェースとして規定しており、FDW開発者はその規定に従って実装します。

PostgreSQLはSQL実行の過程で、FDWによる外部データアクセスが必要な場合にその関数を呼びます。

関数インタフェースの詳細についてはマニュアルの「PostgreSQL 10.4文書 - 56.1. 外部データラッパ関数」を参照してください。

hdfs_fdwの機能的評価

FDWの機能範囲は、マニュアルなどの仕様を記載したドキュメントがあれば簡単に確認できます。一方hdfs_fdwは簡単な説明ドキュメント(readme.md)しかなく、機能範囲が良くわかりません。そこで、hdfs_fdwで実装されている関数の実装を確認し、機能を評価してみたいと思います。

外部テーブルスキャンのための関数(必須)

表1の関数は外部テーブルをスキャンしデータを取得するという基本的な処理を行うものです。FDWの作成に必須の関数のため、hdfs_fdwにおいても全て対応しています。

表1:外部テーブルスキャン関数

関数 概要 対応状況
プランナ GetForeignRelSize 外部テーブルのリレーションサイズ見積もりを取得します。 ○(対応)
GetForeignPaths 外部テーブルに対するスキャンとして可能なアクセスパスを作成します。 ○(対応)
GetForeignPlan 選択された外部アクセスパスからForeignScanプランノードを作成します。 ○(対応)
エグゼキュータ BeginForeignScan 外部テーブルスキャンの実行を開始します。 ○(対応)
IterateForeignScan 外部ソースから一行を取り出して、それをタプルテーブルスロットに入れて返します。 ○(対応)
ReScanForeignScan 先頭からスキャンを再開します。 ○(対応)
EndForeignScan スキャンを終了しリソースを解放します。 ○(対応)

以降の機能は、オプションになります。

外部テーブルの結合をスキャンするための関数

表2に、FDWが外部テーブルをリモートで結合することをサポートする関数を記載しましたが、未対応の状況です。Hadoopは一般的に複数ノード構成のため、外部テーブルをHadoop側で結合しようとすると、中間データのディスク書き込みやノード間のデータ転送が発生し遅くなります。本機能が未対応なのは、結合したデータをあらかじめ作っておくことが推奨されていて、Hadoopではテーブルを結合しない前提であるからと想像します。

ただし、RDBMS側の業務データと連携する場合には、分析などのために結合や集計等の処理を行うと考えられ、そのたびにサーバ側のリソースやネットワーク帯域を圧迫するといった問題が発生します。そのため対応が望まれる機能の一つといえます。

表2:外部テーブルの結合関数

関数 概要 対応状況
GetForeignJoinPaths 同じ外部サーバにある2つ以上の外部テーブルのためのアクセスパスを作成します。 ×(未対応)

スキャン/結合後の処理をプラン生成するための関数

表3に、グルーピングや集約のような処理のリモート実行をサポートする関数を記載しました。やはり未対応なのは、本機能もHadoop側で処理しようとすると非常にコストがかかるためであると想像します。なお、上記の結合処理に比べると対応の優先度は低いといえます。

表3:外部テーブルのスキャン/結合後の処理関数

関数 概要 対応状況
GetForeignUpperPaths 上位リレーション(ウィンドウ関数、ソート、テーブル更新など、全てのスキャン/結合後の問い合わせ)処理のための、ありうるアクセスパスを作成します。 ×(未対応)

外部テーブルを更新するための関数

表4にまとめましたが、更新関数については未サポートと表記があり、利用はできません(TODOリストには、対応したいとの記載がありました)。ただし、HDFSをFDW経由で使用するのは分析・整理などの参照を主とする業務が多いと考えられますので、更新系の機能に対応していなくても、業務への影響は少ないと考えます。

表4:外部テーブルの更新関数

関数 概要 対応状況
AddForeignUpdateTargets 更新や削除の対象行を厳密に識別できるように、UPDATEやDELETEの間に外部テーブルから取得される列のリストに追加の隠された(または「ジャンクの」)ターゲット列を追加します。 ×(未対応)
PlanForeignModify 外部テーブルに対する挿入、更新、削除に必要となる、追加のプラン生成アクションを実行します。 ×(未対応)
BeginForeignModify 外部テーブルへの変更操作の実行を開始します。 ×(未対応)
ExecForeignInsert 外部テーブルにタプルを一つ挿入します。 ×(未対応)
ExecForeignUpdate 外部テーブル内のタプルを一つ更新します。 ×(未対応)
ExecForeignDelete 外部テーブルからタプルを一つ削除します。 ×(未対応)
EndForeignModify テーブル更新を終えてリソースを解放します。 ×(未対応)
IsForeignRelUpdatable 指定された外部テーブルがどの更新処理をサポートしているかを報告します。 ×(未対応)
PlanDirectModify リモートサーバ上で直接変更を実行することが安全かを判断します。 ×(未対応)
BeginDirectModify リモートサーバでの直接変更を実行する準備をします。 ×(未対応)
IterateDirectModify リモートサーバでの直接変更を実行します。 ×(未対応)
EndDirectModify リモートサーバでの直接変更の後、クリーンアップします。 ×(未対応)

行ロックのための関数

表5に行ロックの関数をまとめました。行ロックは基本的に更新処理で使用されるため、更新する関数が未対応の現状では、これらの関数も未対応で問題ないといえます。

表5:外部テーブルの行ロック関数

関数 概要 対応状況
GetForeignRowMarkType 遅延行ロックをサポートするため、行の印付けでどのオプションを外部テーブルに使うかを報告します。 ×(未対応)
RefetchForeignRow ロックした後で、外部テーブルから1つのタプルを再フェッチします。 ×(未対応)
RecheckForeignScan 以前に戻されたタプルが、関連するスキャンおよび結合の制約とまだ一致しているか再検査します。 ×(未対応)

EXPLAINのための関数

表6にEXPLAIN関数の対応状況をまとめました。参照系のEXPLAINは対応、更新系のEXPLAINは未対応と、今までの関数の対応状況とマッチしています。

表6:外部テーブルのEXPLAIN関数

関数 概要 対応状況
ExplainForeignScan 外部テーブルスキャンの追加のEXPLAIN出力を表示します。 ○(対応)
ExplainForeignModify 外部テーブル更新の追加のEXPLAIN出力を表示します。 ×(未対応)
ExplainDirectModify リモートサーバでの直接変更について追加EXPLAIN出力を表示します。 ×(未対応)

ANALYZEのための関数

表7にANALYZEの関数を記載しました。サンプル収集関数は対応していませんが、ANALYZE自体には対応しています。

表7:外部テーブルのANALYZE関数

関数 概要 対応状況
AnalyzeForeignTable ANALYZEが外部テーブルに対して実行されたときに呼び出されます。 ○(対応)
AcquireSampleRowsFunc サンプル収集関数 ×(未対応)

IMPORT FOREIGN SCHEMAのための関数

表8にIMPORT FOREIGN SCHEMAの関数を記載しました。現時点では未対応ですが、データ型の対応に手間がかかるため、対応が望まれる機能の1つといえます。

表8:外部テーブルのIMPORT FOREIGN SCHEMA関数

関数 概要 対応状況
ImportForeignSchema IMPORT FOREIGN SCHEMAを実行する時に呼び出され、外部テーブル作成コマンドのリストを取得します。 ×(未対応)

パラレル実行のための関数

表9にパラレル実行の関数をまとめましたが、現時点では未対応でした。この辺りは、性能向上のためには必要な機能ですが、まず使う上で必要な機能から優先的に対応してほしいと思います。

表9:外部テーブルのパラレル実行関数

関数 概要 対応状況
IsForeignScanParallelSafe スキャンがパラレルワーカーで実行できるかテストします。 ×(未対応)
EstimateDSMForeignScan 並列操作に必要とされるであろう動的共有メモリ量を推定します。 ×(未対応)
InitializeDSMForeignScan 並列処理で必要とされる動的共有メモリを初期化します。 ×(未対応)
ReInitializeDSMForeignScan 外部スキャンプランノードが再スキャンされようとしているときに、並列操作に必要な動的共有メモリーを再初期化します。 ×(未対応)
InitializeWorkerForeignScan InitializeDSMForeignScanでリーダーがセットアップした共有状態に基づくパラレルワーカーのローカル状態を初期化します。 ×(未対応)
ShutdownForeignScan ノードが完了するまで実行されないことが予想されるときにリソースを解放します。 ×(未対応)

以上が、FDWの関数を調査した結果です。機能的な評価としては、最低限の機能は有しており、利用にあたって問題はないと思います。一方、エンタープライズ用途を考えた場合には、現在は未対応ですが以下の点を拡張して運用面を改善することで、利用の促進を図れるのではないかと考えており、そこを期待しています。

  • IMPORT FOREIGN SCHEMAの対応
  • リモート側で結合やソート、集約関数等のpushdownの対応

次回は、hdfs_fdwを実機で利用する際の評価を行いたいと思います。

今回の記事の内容については、NTT OSSセンタの澤田雅彦様にレビューをしていただきました。ありがとうございました。

株式会社 日立製作所
2011年頃から、基幹系でのOSS利活用のためopensource COBOLやPostgreSQLの研究開発や技術支援に従事してきた。2018年から現職となり、PostgreSQL、MySQLのソリューション開発やサポートを担当している。また、PostgreSQLエンタープライズ・コンソーシアム(PGECons)に参画し、PostgreSQLの検証活動や広報活動を行い、PostgreSQLの普及発展に努めている。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています