本章は、PostgreSQLのコアシステムと、テーブルの格納を制御するテーブルアクセスメソッドとのインタフェースを説明します。 コアシステムはこのアクセスメソッドについて、ここで指定されたことのみを把握しています。これにより、追加コードを記述することで全く新しいアクセスメソッド種類を開発することができます。
各テーブルアクセスメソッドはpg_am
システムカタログの行で記述されます。
pg_am
のエントリではテーブルアクセスメソッドの名前とハンドラ関数を指定します。
これらのエントリはSQLコマンドCREATE ACCESS METHODとDROP ACCESS METHODを使って、作成および削除することができます。
テーブルアクセスメソッドのハンドラ関数はinternal
型の引数を一つ取り、table_am_handler
疑似型を返すように宣言されなければなりません。
この引数はハンドラ関数がSQLコマンドから直接呼び出されるのを防ぐためだけのダミーの値です。
関数の結果はTableAmRoutine
型の構造体のポインタでなければならず、そこにはテーブルアクセスメソッドを使用するためにコアコードが知る必要のあるすべてのことが含まれます。
サーバ生存期間の間、戻り値は必要で、通常これはグローバルスコープでstatic const
変数として定義することで達成されます。
アクセスメソッドのAPI構造体とも呼ばれる、TableAmRoutine
構造体はコールバックを使ってアクセスメソッドの振る舞いを定義します。
これらのコールバックは通常のC関数へのポインタで、SQLレベルでは見ることも呼び出すこともできません。
全てのコールバックとその振る舞いは、TableAmRoutine
構造体(とコールバックの必要性を説明する構造体内のコメント)で定義されます。
たいていのコールバックはラッパー関数を持ちます。これらはテーブルアクセスメソッドの(開発者ではなく)使用者の立場でドキュメント記載されています。
詳細は、src/include/access/tableam.h
ファイルを参照してください。
アクセスメソッドを実装するには開発者は通常、タプルテーブルスロットのAM固有の型を実装する必要があります(src/include/executor/tuptable.h
を参照してください)。
これはアクセスメソッド外のコードが、AMのタプルへの参照を保持できるようにして、そのタプルの列にアクセスできるようにするものです。
今のところAMが実際にデータを格納する方法は全く制限されていません。 例えば、postgresの共有バッファキャッシュを使うことも、必須ではありませんが、可能です。 使う場合、おそらく70.6に記述されたPostgreSQLの標準ページレイアウトを使うには有意義でしょう。
現在のテーブルアクセスメソッドAPIのそれなりに大きい制約は、AMが更新および/またはインデックスに対応したい場合、各タプルがブロック番号とアイテム番号から成るタプル識別子(TID)を持つ必要があることです(70.6も参照してください)。
TIDsの下位要素が、例えばheap
に対して持つのと同じ意味を持つことは、厳密には必要ありません。しかし、ビットマップスキャン対応(これは任意です)を望むなら、ブロック番号は局所性を備える必要があります。
クラッシュ安全性のために、AMはpostgresのWAL、あるいは、カスタム実装を使うことができます。
WALを選んだ場合、汎用WALレコードが利用するか、新たなWALレコードタイプを実装することができます。
汎用WALレコードは簡単ですが、大きなWAL容量を伴います。
新たなWALレコード型を実装することは今のところコアコードの修正が必要です(具体的にはsrc/include/access/rmgrlist.h
)。
異なるテーブルアクセスメソッドが単一トランザクション内でアクセスできるという類のトランザクション対応を実装するには、おそらくsrc/backend/access/transam/xlog.c
の仕組みと注意深く統合することが必要でしょう。
新テーブルアクセスメソッド
の開発者は、実装の詳細について、src/backend/access/heap/heapam_handler.c
にある既存のheap
の実装を参照できます。