Presto/Trinoのサブクエリ重複実行問題について

Presto/Trinoは分散クエリを高速に実行するためにストリーミング型のアーキテクチャを採用しているのですが、このためクエリ内に重複箇所があっても複数回並列に実行されてしまうという問題があります。わかりやすい例だと、CTEで定義したクエリを複数回参照した場合、参照した回数分そのクエリの処理が実行されてしまいます。複数回実行されるクエリが重く、参照回数が多い場合、このコストはかなり厳しいものになります。

調べてみたところ、Presto由来のクエリエンジンでいくつかの対策が行われていたのでまとめてみました。

openLookeng

openLookengというのはHUAWEIオープンソースで開発しているビッグデータプラットフォームのようなのですが、クエリエンジンはPrestoをベースとしているようです。こちらではCTEに専用のオペレータを導入し、複数のコンシューマのキューにデータをプッシュできるようになっています。

gitee.com

CTE専用オペレータが導入されていることからCTE以外の共通部分には適用できないのではないかと思いますが、直感的なわかりやすさはあると思います。

PrestoDB

PrestoDBではRaptorXというキャッシュ活用プロジェクトの一環としてクエリフラグメントの出力をワーカーのディスク上にキャッシュするという機能が実装されていました。同一のスプリットが同一のワーカーにアサインされた場合にキャッシュが利用されるというもののようです。

github.com

クエリをまたいでキャッシュを共有できるというのはメリットだと思いますが、実際のワークロードでのキャッシュヒット率がどのくらいか気になるところです。ディスクの消費も激しくなると思うのでユースケースによっては使いづらいのではないかと思いますが、インハウスのデータウェアハウスなど、テーブル数やデータ量がある程度限定されており、ワークロードが予測可能な環境であれば有効かもしれません。

Amazon Athena

AmazonのAthenaではクエリの共通部分をリライトすることでマージしてしまうクエリフュージョンという最適化が実装されているようです。

www.amazon.science

www.amazon.science

この方法は対応可能なケースに制限はあるものの、他の方法と違ってクエリのリライトのみで実現できるためアーキテクチャ非依存であるという利点があります。実際AthenaだけでなくRedshiftなどでも同様の最適化が実装されているようです。Trinoにプルリクエストが出されているのですが、まだマージされていません。実際に動かしてみたのですが、ペーパーで書かれている機能がすべて実装されているというわけではなさそうです。

github.com

ベンチマークだと逆に遅くなってしまうケースもあるようですが、オプションで有効・無効を切り替えられるようになっているので入ってくれると嬉しいですね。

まとめ

問題意識としては同じだと思うのですが、Pretso一族の中でも対策は様々でした。このあたりは各プロダクトが想定するユースケースにもよるところもありそうです。その中でもAthenaのクエリフュージョンはクエリのリライトのみで対応できるので副作用も小さそうですし、比較的気軽に試すことができそうです。

また、Athenaのペーパーにはクエリフュージョンだけでなくスプーリングもロードマップにあると書かれています。それなりに大きな変更になりそうですが、実現の暁にはコミュニティにもなんらかの形でフィードバックされるといいですね。