Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Pluggable Storage in PostgreSQL

Pluggable Storage in PostgreSQL

第34回 PostgreSQLアンカンファレンス (Jul 29, 2022)

Youki Shiraishi

July 29, 2022
Tweet

More Decks by Youki Shiraishi

Other Decks in Programming

Transcript

  1. Pluggable Storage in PostgreSQL 第 34 回 PostgreSQL アンカンファレンス Youki

    Shiraishi † Jul 29, 2022 † NTT Computer & Data Science Laboratories
  2. 自己紹介 名前 白石 裕輝 (Youki Shiraishi) 所属 NTT コンピュータ &

    データサイエンス研究所 興味 トランザクション処理,分散システム,ネットワーク © 2022 NTT Corporation 1
  3. Pluggable Storage PostgreSQL 12 で導入された Pluggable Storage [1, 3] により,テーブルアクセス方式

    (テ ーブル AM) を実装するための API が切られた.これにより,PostgreSQL に組み込まれて いる Heap 以外のテーブル AM の開発・利用が容易になる. 開発者コミュニティでは,以下のテーブル AM の開発が進められている. • Zheap [2] — Undo ログによるストレージエンジン.テーブルデータの肥大化を防ぐ ことができる.EnterpriseDB 社により発表され開発が進められていたが,現在は CYBERTEC 社により開発が進められている. • Zedstore [4] — カラムナ形式のストレージエンジン.OLAP ワークロードを高速に処 理することができる.VMware Greenplum により開発が進められている. © 2022 NTT Corporation 3
  4. PostgreSQL のアーキテクチャ Client Postmaster Backends Database Cluster ($PGDATA) Shared Buffer

    WAL Writer Backgroud Writer Checkpointer Stats Collector Autovacuum Launcher Connect fork() Query fork() PostgreSQL Autovacuum Workers © 2022 NTT Corporation 4
  5. クエリ処理フロー 1. パーサは,クライアントから送信されたクエリ 文字列を解析してパース木を生成する. 2. アナライザは,パース木を分析してクエリの実 行に必要な情報を加えたクエリ木を生成する. 3. リライタは,ビューの展開やルールの適用を行 ってクエリ木を書き換える.

    4. プランナは,適切な結合戦略やアクセスパスを 決定し,プラン木を作成する. 5. エグゼキュータは,プラン木に従って実際の処 理を行う. Parser Analyzer Rewriter Planner Executor Client Query String Raw Parse Tree Query Tree Rewritten Query Tree Plan Tree Backend © 2022 NTT Corporation 5
  6. テーブル AM (PostgreSQL < 12) Parser Planner Executor Heap Buffer

    Manager Storage Manager Page Cache Disk Client Shared Buffer PostgreSQL < 12 Kernel © 2022 NTT Corporation 6
  7. テーブル AM (PostgreSQL ≥ 12) Parser Planner Executor Table Access

    Manager Buffer Manager Storage Manager Page Cache Disk Client Shared Buffer PostgreSQL ≥ 12 Kernel Heap AM Zheap AM Zedstore AM <latexit sha1_base64="h48x7BwR6Sq5HsWs6FQ7M8uBQnQ=">AAAB7XicbVBNS8NAEJ3Ur1q/qh69LBbBU0lE1GPBi8cK9gPaUDabTbt2kw27E6GE/gcvHhTx6v/x5r9x2+agrQ8GHu/NMDMvSKUw6LrfTmltfWNzq7xd2dnd2z+oHh61jco04y2mpNLdgBouRcJbKFDybqo5jQPJO8H4duZ3nrg2QiUPOEm5H9NhIiLBKFqp3WehQjOo1ty6OwdZJV5BalCgOah+9UPFspgnyCQ1pue5Kfo51SiY5NNKPzM8pWxMh7xnaUJjbvx8fu2UnFklJJHSthIkc/X3RE5jYyZxYDtjiiOz7M3E/7xehtGNn4skzZAnbLEoyiRBRWavk1BozlBOLKFMC3srYSOqKUMbUMWG4C2/vEraF3Xvqn55f1lrkCKOMpzAKZyDB9fQgDtoQgsYPMIzvMKbo5wX5935WLSWnGLmGP7A+fwBpwuPFg==</latexit> · · · © 2022 NTT Corporation 7
  8. テーブル AM の実装 新たなテーブル AM を実装する手順は以下のとおり. 1. (オプション) TupleTableSlot{, Ops}

    を実装する. 2. src/include/access/tableam.h で定義されている構造体 TableAmRoutine の 44 個の 関数を実装する1.今回は,特に重要な 5 つの関数 slot_callbacks, tuple_insert, scan_{begin, getnextslot, end} のみ説明する. 3. TableAmRoutine を定義し,その参照を返すハンドラ関数を作成する. 1実装不要な関数もある.src/backend/access/table/tableamapi.c の GetTableAmRoutine を参照のこと. © 2022 NTT Corporation 8
  9. 実装する関数 (抜粋) typedef struct TableAmRoutine { const TupleTableSlotOps *(*slot_callbacks) (Relation

    rel); void (*tuple_insert) (Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate); TableScanDesc (*scan_begin) (Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, ParallelTableScanDesc pscan, uint32 flags); bool (*scan_getnextslot) (TableScanDesc scan, ScanDirection direction, TupleTableSlot *slot); void (*scan_end) (TableScanDesc scan); } TableAmRoutine; © 2022 NTT Corporation 9
  10. テーブル AM の実装: TupleTableSlot (1) エグゼキュータは,“タプルテーブル” に格納されたタプルを操作することでクエリの処 理を行う.各タプルは src/include/executor/tuptable.h で定義されている構造体

    TupleTableSlot (TTS) で表現され,タプルテーブルは TTS のリストとして表現される. テーブル AM を実装する場合,TTS 自体の実装と,TTS に対する各種操作の実装が必要に なる.TTS に対する一連の操作は,構造体 TupleTableSlotOps (TTSOps) で定義される.テ ーブル AM の実装には,この TTSOps を返す slot_callbacks 関数の実装が必要である. const TupleTableSlotOps *(*slot_callbacks) (Relation rel); © 2022 NTT Corporation 10
  11. テーブル AM の実装: TupleTableSlot (2) PostgreSQL には,以下の 4 種類の TTS{,

    Ops} が実装されている2 が,これらを利用せず, 独自に定義した TTS をテーブル AM で利用することもできる. • BufferHeapTupleTableSlot — ディスクバッファページ上の物理 Heap TTS. • HeapTupleTableSlot — メモリコンテキスト上に確保された物理 Heap TTS. • MinimalTupleTableSlot — メモリコンテキスト上に確保された物理 Heap TTS.シス テムカラムを持たない. • VirtualTupleTableSlot — tts_{isnull, values} で構成される仮想 TTS.他の TTS のよう に slot_deform_heap_tuple 関数で物理タプルから tts_{isnull, values} を構成する必 要がない.システムカラムを持たない. 2src/include/executor/tuptable.h, src/backend/executor/execTuples.c © 2022 NTT Corporation 11
  12. テーブル AM の実装: タプルの挿入 テーブルにタプルを挿入する際は,tuple_insert 関数が呼び出される. 挿入先のリレーションと,TTSOps と挿入する値の埋め込まれた TTS が与えられるので,

    これらを用いて適切な方法でストレージにタプルを挿入する処理を実装する. void (*tuple_insert) (Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate); © 2022 NTT Corporation 12
  13. テーブル AM の実装: テーブルスキャン (1) テーブルスキャン時には,scan_{begin, getnextslot, end} 関数が呼び出される. スキャン開始時には

    scan_begin 関数が呼ばれ,スキャン対象のリレーションやスナップ ショット,スキャンキー等が与えられるので,これらを用いて構造体 TableScanDesc (ス キャン中に保持する一時的な情報) を malloc する処理を実装する. TableScanDesc (*scan_begin) (Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, ParallelTableScanDesc pscan, uint32 flags); © 2022 NTT Corporation 13
  14. テーブル AM の実装: テーブルスキャン (2) scan_begin 関数の実行後は,テーブルスキャンを実行してタプルデータを取得する scan_getnextslot 関数が呼び出される.TableScanDesc と取得したデータの格納先の

    TTS が与えられるので,これらを用いてストレージからタプルを 1 つだけ取り出し,TTS に格 納する処理を実装する.スキャン対象のタプルがなくなった場合に false を,それ以外の 場合は true を返すように実装する. bool (*scan_getnextslot) (TableScanDesc scan, ScanDirection direction, TupleTableSlot *slot); © 2022 NTT Corporation 14
  15. テーブル AM の実装: テーブルスキャン (3) スキャン対象のタプルがなくなる (i.e., scan_getnextslot 関数が false

    を返す) と,最後に scan_end 関数が呼ばれる.この関数には,malloc されている TableScanDesc や取得済 みスナップショットの開放処理を実装する. void (*scan_end) (TableScanDesc scan); © 2022 NTT Corporation 15
  16. テーブル AM の実装: ハンドラ関数 (1) これまで説明した関数を含む計 44 個の関数を実装したあとは,それらの関数を用いて構 造体 TableAmRoutine

    を定義し,その参照を返すハンドラ関数を実装する. static const TableAmRoutine heapam_methods = { .type = T_TableAmRoutine, .slot_callbacks = heapam_slot_callbacks, ... }; Datum heap_tableam_handler(PG_FUNCTION_ARGS) { PG_RETURN_POINTER(&heapam_methods); } © 2022 NTT Corporation 16
  17. テーブル AM の実装: ハンドラ関数 (2) 実装したテーブル AM を有効化すると,ハンドラ関数がシステムカタログに登録される. テーブルアクセスは,ハンドラ関数によって返される TableAmRoutine

    を経由し,実装し た関数を用いて行われる. =# SELECT * FROM pg_am WHERE amtype='t'; oid | amname | amhandler | amtype -----+--------+----------------------+-------- 2 | heap | heap_tableam_handler | t (1 row) =# CREATE TABLE heap_tab (foo int, bar int) USING heap; CREATE TABLE © 2022 NTT Corporation 17
  18. テーブル AM 開発の注意点 テーブル AM は発展途上である.例えば, • PostgreSQL 15 から

    ALTER TABLE ... SET ACCESS METHOD ... が可能になった. • PostgreSQL 16 で RelFileNode が RelFileLocator に変更され,テーブル AM API にも影 響があった. また,未だに Heap AM を前提としたコード断片が散見される.例えば, • TTS の tts_tid は,32-bit のブロック ID と 16-bit のオフセット番号からなる 48-bit ItemPointer であり,テーブルサイズが制限される.また,この tts_tid はインデック スのないテーブルを前提としているため,プライマリキーを tts_tid とするインデッ クス付きのテーブルの実装は制限される. © 2022 NTT Corporation 18
  19. デモ C++ の std::map を使ったシンプルなインメモリ型テーブル AM を実装した. stonewhitener/cxxmapam: https://github.com/stonewhitener/cxxmapam •

    単純な INSERT と SELECT クエリのみをサポートする • 挿入するすべての値は非 Null かつ Pass-by-Value 型とする • インデックスやトランザクションをサポートしない • ログやチェックポイントは実装しない © 2022 NTT Corporation 19
  20. デバッグ用の Makefile の作成 効率的に開発を進めるために,デバッグ用の PostgreSQL をビルドする. 残念ながら CLion は PostgreSQL

    のソースツリーで Autotools を正しく認識しないため, ここでは,次のようにオプションを指定して手動で configure を実行する56. $ git clone https://git.postgresql.org/git/postgresql.git $ cd postgresql $ ./configure --prefix=$HOME/.local/pgsql \ --enable-debug \ --enable-cassert \ CFLAGS=-O0 5https://www.postgresql.org/docs/current/install-procedure.html 6https://wiki.postgresql.org/wiki/Developer_FAQ © 2022 NTT Corporation 21
  21. CLion でプロジェクトを開く あとは CLion で PostgreSQL のソースツリーを開くだけでよい. 1. File →

    Open... から configure 済みのソースツリーを選択する. 2. プロジェクトを clean するように言われるので従う. 3. Makefile の分析が開始されるので完了を待つ. 4. Ready to hack! Tips. • デバッガをバックエンドプロセスにアタッチするには,Run → Attach to process... から適切なプロセスを選択する. • プロジェクトが正しく分析されない場合は,Build → Clean and Reload Makefile Project からリロードすると直ることが多い. © 2022 NTT Corporation 22
  22. References (1) [1] A. Freund. Pluggable table storage in PostgreSQL.

    In PGCon 2019, 2019. [2] A. Kapila and R. Haas. zheap: less bloat, fewer writes, and just plain smaller. In PGCon 2018, 2018. [3] H. Kommi and P. Kapoor. Pluggable table access methods (pluggable storage). In PGCon 2019, 2019. © 2022 NTT Corporation 24
  23. References (2) [4] A. Wang and S. Chakraborty. Zedstore -

    in-core column store for Postgres. In PGCon 2020, 2020. © 2022 NTT Corporation 25