Our Technologies

GPUをデータベース処理に適用するというアイデアがまだほとんど存在しておらず、どのようにソフトウェアを設計すれば良いのか誰も知らなかった2012年に、現在のPG-Stromの原型となるプロトタイプを公開して以来、私たちは様々な試行錯誤を積み重ねてきました。中には結局上手く機能せず、お蔵入りとなったものも存在します。

こちらのページでは、GPUをデータベース処理に適用するという私たちの10年の歩みの中で、現在のPG-Stromを支える中核技術となった各種の要素技術をご紹介します。

GPU-Direct SQL

P2P-RDMA技術を用いて、NVME-SSDなど高速ストレージからGPUデバイスへ直接データを転送し、データがCPU/RAMに到着するより前に、SQLを並列処理して不要なレコードを削減、集計処理まで済ませてしまう事で、ホストシステム(PostgreSQL)が処理すべきレコード数を圧倒的に少なくする技術です。

P2P-DMA (Peer-to-Peer Direct Memory Access) 技術というのは、PCI-Eバスに接続されたGPUやNVME-SSDなどのデバイス同士で(ホストシステムのRAMを介さずに)直接データを転送する技術です。また、Infinibandなど高速ネットワークを介して「SSD -> NIC -> (network) -> NIC -> GPU」というパターンでデータ転送を行う事もあり、こちらは P2P-RDMA (Remote DMA) と呼ばれます。どちらの場合でも、ホストシステムのバッファを経由せずにデータを転送でき、ハードウェアのカタログスペックに近いデータ転送スループットを期待できます。

2017年に実用化したGPU-Direct SQL技術は、HeteroDBの独自Linux kernelドライバがNVME-SSDとGPUの間のP2P-DMAを仲介することで、NVME-SSDのハードウェア限界に等しいスループットでデータを読み出し、PCI-E 3.0世代では最速の水準となるGPUあたり10GB/sのデータ処理速度を実現しました。

以下のグラフは、Star Schema Benchmarkを利用して、ローカルNVME-SSDx4、およびGPUx1の基本構成における処理性能(秒あたり処理行数、および読み出しスループット)をプロットしたものです。行データ(PostgreSQL Heap)同士の比較においても、データ転送のロスが少ない分、GPU-Direct SQLがFilesystem経由のI/Oに比べ3倍程度のスループットを記録しており、さらに、I/Oの効率が良い列データ(Apache Arrow)においては、文字通り「桁違い」の処理性能を発揮している事が分かります。

その後、2021年には上記の独自Linux kernelドライバと同等の機能が、NVIDIA社よりGPUDirect Storageという名称でCUDA Toolkit 11.4に統合され、PG-StromにおいてもRed Hat Enterprise Linux 8.x系列、およびUbuntu Linux向けにはGPUDirect Storageドライバを利用するように対応が強化されています。

これにより、GPU-Direct SQL機構はローカルのNVME-SSDだけでなく、NVME-oFやNFSoRDMAなどリモートで拡張可能なストレージからのP2P-RDMAも利用できるようになり、SDS (Software Defined Storage) などと併せて、業務システムに必要なストレージ管理とパフォーマンスを並立する事が可能となりました。

GPU-Direct SQL with NFS-over-RDMA

GPU-Direct SQLの応用として、共有ファイルシステム(NFS)から100Gb-Ethernetなど高速RDMAネットワークを介して、GPUへの直接データ読み出しを行う事ができます。

Ext4やXfsなどローカルのファイルシステムと比べ、NFSは頻繁な更新を伴うトランザクション用データ(例:PostgreSQLテーブル)の保存先としては不向きです。しかし、後述のApache Arrow形式ファイルのように追記のみのデータを保存し、それを大量に読み出すワークロードに対しては、GPU-Direct SQLとNFS-over-RDMAを併用する事で、ほぼネットワークの帯域に近いデータ転送レートでGPUへデータを供給する事ができます。

NFSは共有ファイルシステムですので、例えば、IoT/M2M系のログデータを収集するサーバがどんどんNFSサーバにApache Arrowファイルを書き出し、一方で、検索・集計処理の際はGPUを搭載したDBサーバが、これをネットワーク帯域の上限に近いスピードで読み出すといったシステム構成も可能です。

Arrow_Fdw

Apache Arrowとは列形式・構造化データ向けのフォーマットの一つで、多くのデータ分析アプリケーションが共通で利用する事のできるデータ交換用のフォーマットでもあります。そのため、C/C++やPythonなど、多くの言語でArrow形式を扱うためのライブラリが整備されています。

PG-StromはPostgreSQLの外部テーブル(Foreign Table)機能を利用して、Apache Arrow形式ファイルをあたかもPostgreSQLテーブルであるかのように読み出すための機能、Arrow_Fdwを提供しています。GPU-Direct SQLを利用した直接読み出しにも対応しており、また、バルクインサートであれば、Apache Arrow形式ファイルの末尾に追記も可能です。

なぜデータのインポートが不要なのか?

通常、外部からデータを取り込んでDBで集計・解析を行う場合には、INSERTCOPY FROMを用いたりと、インポート処理に相応の時間を要するのが通例でした。しかしPG-StromのArrow_Fdwであれば、外部ソフトウェアによって作成されたApache Arrowファイルを外部テーブルとしてマップするだけ、つまり大量レコードの取り出しと再書き込みを伴わないため、単純なOS上のファイルコピーだけで全て完了です。

なぜI/Oが効率的なのか?

集計・解析系の処理では、テーブルに定義された全ての列を参照することは稀です。通常は一部の列だけを参照すれば十分で、言い換えれば、被参照列以外のデータは「ゴミデータ」であり、I/Oの帯域を無用に圧迫する事になってしまっています。

PostgreSQLのような行データでは被参照列のみをストレージから抽出する事は困難ですが、列データの場合は、列ごとにデータが隣接配置されているため、被参照列のデータだけをストレージから読み出すよう、デバイスを制御するのは容易です。

min/max統計情報と範囲インデックス

Apache Arrow形式は、その内部にRecordBatchと呼ばれるデータのまとまりを複数個持つように構成されています。RecordBatchとは要素数の等しい配列を集めたデータ構造です。例えば、全体で10億行を持つArrowファイルの内部に、それぞれ100万行を有するRecordBatchが1,000個ある、という構成をとる事もあります。

min/max統計情報とは、Apache Arrow形式でアプリケーションが自由に利用できるメタデータ(Custom Metadata)フィールドを利用して、RecordBatchごとの最大値・最小値を埋め込んでおくものです。後述の pg2arrow コマンド、および pcap2arrow コマンドが対応しています。

例えば検索条件に「ymd BETWEEN '2020-01-01' AND '2020-12-31'」という条件が与えられた場合、ymd列の最大値が'2020-01-01'未満であるRecordBatch、および最小値が'2020-12-31'より大きなRecordBatchに関しては、その中身を読み込むまでもなく検索条件にヒットするレコードは1件も存在しない事が分かります。

Arrow_FdwでApache Arrowファイルを読み出す際には、min/max統計情報を参照し、明らかに不要なRecordBatchはそもそも読み出しを行いません。Arrow形式は列データ構造を持っていますので、元々不要な列を読み飛ばすことでI/Oの効率化を行っていますが、それに加えて、不要なRecordBatch(行のまとまり)を読み飛ばすことで、更なるI/Oの効率化を行っています。

Pg2Arrow / Mysql2Arrow

多くのデータ分析アプリケーションがApache Arrowに対応しているとは言っても、
比較的新しいデータ形式であるため、手元のシステムはRDBMSで構築されている、
エンジニアの習熟に時間がかかるといった事が障害になっているかもしれません。

PG-Stromに同梱のツール pg2arrow および mysql2arrow は、それぞれ、PostgreSQLやMySQLにクエリを投げ、その結果をApache Arrow形式ファイルとして保存します。

単純にテーブルをダンプするだけでなく、例えば別のテーブルとJOINした結果を出力したり、条件を指定してフィルタリングしたり、結果をソートして出力したりといった使い方も可能です。

これらのコマンドを利用する事で、Arrow_Fdwを介してArrow形式ファイルを読み出すだけでなく、逆に既存のデータベースからArrow形式ファイルを生成する事も可能です。

Pcap2Arrowによるパケットキャプチャ

ネットワークの高速化と共に、パケットキャプチャのサイズは増大し、セキュリティ事故発生時のキャプチャファイル検索の難易度は増大しています。

PG-Stromに同梱のツールpcap2arrowは、システムのネットワークインターフェースから直接、またはキャプチャ済みのPCAPファイルから、パケットログを標準的なSQLで検索可能な形で Apache Arrow 形式に変換する事ができます。

NICから直接キャプチャを行う際には、Linux kernel内でバッファリングを行い、10Gbを越える高速ネットワークでも取りこぼしを最小化する事のできるPF_RINGドライバを使用し、さらにマルチスレッドでの受信・書き込みを行って、高速なキャプチャに対応しています。

一度Apache Arrow形式に変換してしまえば、あとは標準的なSQLを用いて、様々な検索条件の下でパケットログを検索する事が可能になります。もちろん、GPU-Direct SQLによる高速な読み出しや、min/max統計情報を使った絞込みにも対応しています。

GPU版PostGIS

例えば携帯電話のGPS情報を元に『ある一定のエリアに存在するデバイスを抽出したい』といったクエリを処理する場合、緯度・経度で示された現在位置が、複雑な形状をしたエリアの中に含まれているかどうかを判定しなければいけません。

PostGISには、こういったケースに利用できるSQL関数や演算子が多数定義されており、点や線、多角形(ポリゴン)といったジオメトリ要素を用いたデータベースの検索に関しては、デファクトスタンダードと言える存在です。

PG-Stromでは、そのPostGISが提供するSQL関数や演算子の一部をGPUで実行する事が可能です。例えば、ある座標が特定のエリアに含まれているかどうかを判定する st_contains() 関数は、複雑な形状のポリゴンにも対応しているため、これを愚直に実装すると相応にプロセッサ負荷の高い処理となりますが、これをGPUで並列実行する事で応答速度の改善が図れます。

GpuJoinでのGiST-Index (R木) サポート

PG-Stromの他にもGIS関数に対応しているGPU-Databaseはいくつか存在しますが、GPU上でインデックスを用いた絞込みに対応しているのは、PG-Stromのみです。

元々PostGISは、R木と呼ばれるデータ構造を用いて点やポリゴンなどのジオメトリ要素をインデックス化し、検索条件に合致するジオメトリ要素の絞り込みと検索の高速化に利用していました。

GpuJoinのテーブル結合条件にR木インデックスを利用できるとオプティマイザが判定した場合、PG-StromはインデックスをGPUにロードし、これを利用して効率的な絞り込みを行います。

原理上、インデックスの探索は他のスレッドとの競合を考えることなく、並列に実行する事ができるため、コア数の多いGPUにとっては理想的なワークロードです。CPU並列クエリと比較して200倍の高速化を達成した事例もあり、従来はバッチ的に処理せざるを得なかったワークロードを、リアルタイムに処理する事が可能になるといった、質的な変化を引き起こす可能性を持った機能です。