発病活動 – Understanding SQL and RDB

もうちょっとデータベースというか RDB なり SQL なりのクエリの実行というものをきちんと理解したい気がする。DuckDB をいじっていた時に感じた物足りなさ、覚束なさや ZetaSQL を読んでわからない感じは、そういうリテラシの不足に起因している気がするので。

データベースといっても B-Tree みたいなストレージの話やトランザクションなど話題は色々あるけれど、ここでの関心はクエリの評価。結局自分にとっての SQL は Dremel や BQ のような OLAP で、そこで SQL という宣言的なクエリがデータを読むコードになって評価される魔法を理解したい欲求がある。

というわけで問題を理解するにあたり必要なことを考える。

  • 教科書を読む。長くてかったるいのでできれば論文を読んで済ませたいが、どうかね。大学のコース資料をいくつかあたって、必要な reading list を作るところからスタートだろうか。
  • しょぼい toy query processor を書く。オンメモリのデータか、ごく単純なフォーマットのファイル (mmap で使えるようなやつ) を相手にいくつかの素朴な代数的クエリが書ければよい。といってもそれなりに難しそうだけど。

しかしデータベースとか何で書けばいいのかね。C++ とか Java とかが堅いのはわかるが、そんなもの課外活動で書きたくない。一方でさすがに Python とか JS とかいう類の題材でもない。モダンプログラマなら Go なり Rust なりで書くんだろうけど。いい機会だから Rust 軽く勉強しようかなあ。全然本題が進まなそうだけど・・・まあ本題が進まなくても Rust を触れるならそれはでいい気はする。query processor 書きは題材ということで。

つまり、昼休みは RDB の教科書なり論文なりを読み、朝は Rust のチュートリアルをやる。これだな。可視化の教科書は読みかけだけど中断。SQL/RDB に詳しくなる方が楽しそうなので。課外活動は中断挫折を気にせずやってきます。

読譜活動 – ZetaSQL – Algebrizer

さて間が空いてしまったが続けます。04:07. ベッドから直行してしまったが、あとで着替えコーヒー休憩が必要。

  • evaluator.h および evaluator_base.h を見ると、評価は PreparedStatement という形で API になっていることがわかる。Execute() というメンバ関数がある。
  • そして internal::Evaluator という非公開クラスに移譲される。
  • このクラスは SQL を Prepare() のち ExecuteAfterPrepare() する。
  • Prepare() は要するに Analyzer すなわち resolved AST を作るんでしょ・・・と思いきや、それに加えて Algebrizer というのがあるな。
  • Algebrizer::AlgebrizeQueryStatementAsRelation() という関数が呼ばれているので見てみるとジャンプ先の algebrizer.cc は突然 5000 具合あってギャーっとなる。関係代数に変換するということなのだろうか・・・。
  • 関数の出力は RelationalOp クラス。これは operator.h に定義されている AlgebraOp のサブクラスで、Yet another tree を構成している。そういえば Duck にも Logical op だの physical op だのがあったね。つまり Algebrizer はいわゆる planner なのだな。
  • で Resolved AST を traverse して Algebra tree に変換していく。たとえば ResolvedTableScan は TableScanOp になる by AlgebrizeTableScan() この辺の方のデザインは duck もだいたい同じで duck と zeta が互いをコピーするのはタイミング的にどう考えても不可能なので、なんか元ネタというか系譜があるな。どこから来たのだろうねこのデザイン/アーキテクチャ。

ここから先は自分の関係代数というかデータベースリテラシ不足で読んでもわからん感。修行して出直す必要がありそう。

肝心の Evaluation はまだ読んでないけど、理解のない状態でこれ以上読み進めても不毛なので Zeta Reading はここまで。