dev@arrow.apache.org を見てたら、Rust で Query Engine を書いている話が出ていた。これは Apache Arrow の Commiter である Andy Grove が作っている DataFusion というプロジェクト。

https://github.com/andygrove/datafusion

The current code supports single-threaded execution of limited SQL queries (projection, selection, and aggregates) against CSV files. Parquet files will be supported shortly.

まだ作り始めらしく、一部のクエリがシングルスレッド動くところまでできている。

The TL;DR is that this project is a great way to learn about building a query engine but this is quite early and not usable for any real world work just yet.

「このプロジェクトは Query Engine の作り方を学ぶのに適している」とあり、現時点ではかなりコードが少ないので、コードを眺めて雰囲気を感じ取ってみた。( ※ 私は Rust は読んだことも書いたことも無いので )

Current Code

Data Source としては今のところ CSV をサポートしている。Parquet も近々サポートする予定とのこと。中で使われている CSV ファイルの Reader は Arrow のモジュール( arrow::csv ) で、RecordBatch にデータが詰められるようになっている。

SQL Parser の本体は別のモジュールになっている。これも Andy Grove 作。このモジュールを使って SQL 文を AST に変換している。

https://github.com/andygrove/sqlparser-rs/blob/master/src/sqlparser.rs

Logical Plan は AST Node に含まれる要素から [ projection, relation, selection(filter), limit order by, group by, having ] を取り出し、それぞれの有無を見ながら構築している。現時点では、Aggregation かどうかは Select 句に Function が存在するかどうかで判断している。

今のところ、Logical Plan を optimize する、という処理は入っていない。ただ、Logical Plan を構築した後に push_down_projection という関数を呼び出そうとしてコメントアウトしているので、そのうち入りそう。

Logical Plan 構築後、それぞれの要素を Relation に変換していく。PhysicalPlan という enum もあるものの、特に使われていないようだ。現状実装されているのは、DataSourceRelation, FilterRelation, ProjectRelation, AggregateRelation の4つ。

実際の処理内容は各 Relation に書かれている。Relation は next という関数を持つ。この関数が呼び出されると、上位(input)の next が呼び出される。Relation の中で行われる式の評価の一部は Arrow 側で行われている( arrow::array_ops )。

Conclusion

非常にシンプルな構成なので、Query Engine の作り方を学ぶ為に暫くこのプロジェクトを Watch しようかなと。また、先にメールにあるように、Protobuf 経由で Gandiva に繋ぎたい、ということなので、それも興味がある。