PostgreSQL解析ドキュメント

Similar documents
自己紹介 長田悠吾 (Yugo Nagata) SRA OSS, Inc. 日本支社 PostgreSQL 技術支援 コンサルティング PostgreSQL インターナル講座講師 研究開発 Copyright 2018 SRA OSS, Inc. Japan All right

プログラミングI第10回

PowerPoint Template

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

Microsoft PowerPoint - CproNt02.ppt [互換モード]

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

プログラミング基礎I(再)

Microsoft PowerPoint - lec10.ppt

Undestand の解析 Understand の C 言語で抽出できない依存関係について サンプルコードを用いて説明します 確認バージョン Understand 3.0 (Build 640) Understand 3.1 (Build 700) Understand 4.0 (Build 78

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤

Microsoft PowerPoint - 09.pptx

slide5.pptx

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

memo

memo

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

二分木の実装

Microsoft Word - no11.docx

memo

Microsoft PowerPoint - handout07.ppt [互換モード]

Microsoft PowerPoint - kougi9.ppt

CプログラミングI

(2) 構造体変数の宣言 文法は次のとおり. struct 構造体タグ名構造体変数名 ; (1) と (2) は同時に行える. struct 構造体タグ名 { データ型変数 1; データ型変数 2;... 構造体変数名 ; 例 : struct STUDENT{ stdata; int id; do

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

プログラミング実習I

Microsoft Word - matlab-coder-code-generation-quick-start-guide-japanese-r2016a

memo

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

講習No.12

Microsoft Word - Cプログラミング演習(8)

PowerPoint プレゼンテーション

Taro-ポインタ変数Ⅰ(公開版).j

JEB Plugin 開発チュートリアル 第4回

PowerPoint プレゼンテーション

Microsoft PowerPoint pptx

1. 入力した正の整数を降順に並べ換えて出力するプログラムを作成せよ プログラムは個別にコンパイルし make コマンドで実行すること 入力データは 50 以下とし 以下の数が混在しているとする 16 進数 : 先頭 1 文字が x または X( エックスの小文字か大文字 ) 8 進数 : 先頭 1

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

PowerPoint プレゼンテーション

デジタル表現論・第6回

生成された C コードの理解 コメント元になった MATLAB コードを C コード内にコメントとして追加しておくと その C コードの由来をより簡単に理解できることがよくありま [ 詳細設定 ] [ コード外観 ] を選択 C コードのカスタマイズ より効率的な C コードを生成するベストプラクテ

株式会社アルウィン C 言語コーディング規約 ver.0.1

PowerPoint プレゼンテーション

Microsoft Word - Android_SQLite講座_画面800×1280

プログラミング基礎

プログラミング入門1

intra-mart Accel Platform — IM-BloomMaker プログラミングガイド   初版  

Prog1_10th

Taro-リストⅢ(公開版).jtd

第 2 章 PL/SQL の基本記述 この章では PL/SQL プログラムの基本的な記述方法について説明します 1. 宣言部 2. 実行部 3. 例外処理部

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

PowerPoint プレゼンテーション

メール全文検索アプリケーション Sylph-Searcher のご紹介 SRA OSS, Inc. 日本支社技術部チーフエンジニア Sylpheed 開発者 山本博之 Copyright 2007 SRA OSS, Inc. Japan All right

プログラミング入門1

Microsoft Word - no103.docx

Microsoft Word - Training10_プリプロセッサ.docx

Microsoft PowerPoint - 11.pptx

Microsoft PowerPoint - 計算機言語 第7回.ppt

PowerPoint プレゼンテーション

2006年10月5日(木)実施

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y 小幡智裕

データ構造

PowerPoint プレゼンテーション

Microsoft Word - no15.docx

Prog1_15th

ソフトウェア基礎 Ⅰ Report#2 提出日 : 2009 年 8 月 11 日 所属 : 工学部情報工学科 学籍番号 : K 氏名 : 當銘孔太

演算増幅器

Taro-リストⅠ(公開版).jtd

02: 変数と標準入出力

デジタル表現論・第4回

wireshark dissector with lua

プレポスト【問題】

Microsoft Word - no202.docx

PowerPoint プレゼンテーション

Microsoft Word - Cプログラミング演習(12)

Microsoft Word - no12.doc

プロセス間通信

Java講座

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

PowerPoint プレゼンテーション

Microsoft Word - Cプログラミング演習(11)


intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

Microsoft PowerPoint ppt

Microsoft PowerPoint - 6.pptx

Microsoft PowerPoint pptx

Microsoft PowerPoint - 説柔5_間勊+C_guide5ï¼›2015ã•’2015æŒ°æŁŽæš’å¯¾å¿œç¢ºèª“æ¸‹ã†¿ã•‚.pptx

memo

Microsoft Word _VBAProg1.docx

JavaScript 演習 2 1

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

gengo1-11

Microsoft PowerPoint - 05.pptx

Taro-スタック(公開版).jtd

02: 変数と標準入出力

C 言語第 7 回 掛け算 (multiply number) ìz1 = x1 + iy1 í îz = x + iy 割り算 (devide number) ( )( ) ( ) Þ z z = x + iy x + iy = x x - y y + i y x + x y

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

Transcription:

PostgreSQL 解析資料 ~ node 構造 ~ ( 株 ) NTT データ オープンソース開発センタ 井久保寛明 1. はじめに 本ドキュメントでは PostgreSQL のクエリコンパイル全般に使われている node 構造について説明している node 構造は クエリのコンパイルで木構造が必要なところで使用されている 例えば SQL 文をパージングしたあとのパーズ木やクエリの実行プランなどに使われている node 構造は クエリコンパイルの他にもメモリコンテキストの木構造の保持にも利用されている 本ドキュメントでは 基本的に クエリ処理について話を進める メモリコンテキストの詳細については PostgreSQL 解析資料 ~メモリ管理 ~ を参考にして欲しい 1.1. 対象バージョン本ドキュメントは PostgreSQL8.0.1 を対象にソースコードの調査を行ったものである 従って 他のバージョンでは 内容が異なる場合があるので注意して頂きたい 1.2. PostgreSQL のクエリコンパイル処理 node 構造を説明する上で クエリコンパイルに使われる様々な木構造の名称が出てくるので ここで PostgreSQL のクエリコンパイル処理の概要を説明する PostgreSQLのクエリ処理の全体の流れを表したのが 図 1-1である まず テキストで渡された SQL 文に対して 字句解析と構文解析を行って パーズ木を生成する 字句解析とは 文字列から意味のある塊 ( トークン ) を切り出すことである 構文解析とは 字句解析で切り出したトークンを 構文規則に合っているかチェックし 構文規則に合わせて木構造のデータを生成していくことである こうして作成されたのがパーズ木である 次に 作成されたパーズ木に対して意味解析を行う 意味解析では 指定されたテーブルが実際にあるか確認したり 複数の SQL 文に置き換えて実行する構文の場合 SQL 文の変換を行ったりする そして 意味解析の結果としてクエリ木が生成される 続いて リライト処理として ユーザ定義のルールが定義してある場合にはクエリの変換処理を行う リライトの結果もクエリ木である 最後に クエリ木は プランナ ( オプティマイザ ) に渡される プランナでは 論理クエリプランを生成して 最終的には1つの物理実行プランが書かれたプラン木を生成する このときにパスツリーと呼ばれる 同じ実行結果になる複数の異なる実行プランが生成され その中で最適なものをコスト 1/8

ベースで選択する 最終的に選択されたパスツリーをプラン木に変換し そのプラン木をクエリエグゼキュータに渡して SQL の処理を実行する 以上が PostgreSQL のクエリ処理の概要である SQL 文 クエリコンパイラ select * from foo where id = 1; 字句解析構文解析 意味解析 リライター パーズ木 クエリ木 プランナ ( オプティマイザ ) クエリ木 クエリエグゼキュータ 最適なプランを選択してプラン木を生成 論理クエリプランの生成 プラン木 論理クエリプラン パスツリー ( コスト計算のため多数作成する ) 図 1-1 PostgreSQL のクエリコンパイル処理 2. node 構造 PostgreSQL では SQL のコンパイル処理に使われる木構造を操作するために src/backend/nodes ディレクトリ以下にある node 構造を使用する 一番基本的な Node 構造体の構造は 次のようになっている typedef struct Node } Node; #define nodetag(nodeptr) (((Node*)(nodeptr))->type) 見てのとおり ノードの型が分かるだけである ちなみに define で定義されている nodetag というマクロで Node 型の中から type を取り出せるようになっている Node 型の使い方は 木構造のデータを Node 型として関数に渡し 関数内で先頭の type をチェックして処理を分岐し 分岐後にキャストを行って処理を継続するというようになる 従って デバッガなどを使ってソースコードを追っている場合 Node 型を調べる場合には type をチェックして 実際の構造体に当てはめて考える必要がある 2/8

Node 型は 処理分岐の前に使用する型で 実際にノードの処理を行う際には それぞれ必要な構造体 にキャストされる 例えば パーズ木中のカラム名のノードは次のように定義されている typedef struct ColumnRef List *fields; field names (list of Value strings) List *indirection; subscripts (list of A_Indices) } ColumnRef; このキャストする様子を図に表すと 図 2-1のようになる このように ColumnRef 構造体をNode 構 造体にキャストしても type だけは正しく読めるのである Node 構造体 (Node 型 ) ColumnRef 構造体 Plan 構造体 typedef struct Node } Node; typedef struct ColumnRef List *fields; List *indirection; } ColumnRef; typedef struct Plan Cost startup_cost; Cost total_cost; double int } Plan; plan_rows; plan_width; 図 2-1 Node 構造体のキャストの仕組み ColumnRef だけでなく Plan 構造体やその他多数のノード用の構造体がある 次に 処理の分岐の例であるが 次のようになっている まず ノードの型を取り出すために 前述の nodetag() マクロにかけ その結果の型で switch 文で処理を分岐するというようになっている void * copyobject(void *from) void *retval; if (from == NULL) return NULL; switch (nodetag(from)) * PLAN NODES case T_Plan retval = _copyplan(from); break; case T_Result 3/8

retval = _copyresult(from); break; 例えば Node の type が T_Plan であれば _copyplan(from) が呼び出される _copyplan() では 引数のキャストが行われ Node 型から Plan 構造体に変換されて処理が継続する Plan 構造体は 次のように定義されている typedef struct Plan * estimated execution costs for plan (see costsize.c for more info) Cost startup_cost; cost expended before fetching any * tuples Cost total_cost; total cost (assuming all tuples * fetched) * planner's estimate of result size of this plan step double plan_rows; number of rows plan is expected to emit int plan_width; average row width in bytes 先頭が NodeTag 型の type になっているので type を見るだけなら Node 型として見ても問題ない訳である 2.1. NodeTag ここでは Node 型の type をもう少し詳しく見ていく Node 型の type は NodeTag という enum 型で定義されたものである include/nodes/nodes.h に次のように定義されている typedef enum NodeTag T_Invalid = 0, * TAGS FOR EXECUTOR NODES (execnodes.h) T_IndexInfo = 10, T_ExprContext, T_ProjectionInfo, T_JunkFilter, T_ResultRelInfo, T_EState, T_TupleTableSlot, 4/8

* TAGS FOR PLAN NODES (plannodes.h) T_Plan = 100, T_Result, Node 型は 様々なモジュールで使われることから NodeTag に割り当てられる番号が それぞれの目的毎に分けられている また Node 型の type に対応する構造体は それぞれ次の表のファイルで定義されている 例えば T_Plan は 100 番であり T_Plan に対応する Plan 構造体が格納されているのは plannodes.h ということになる Node の種類 構造体の定義されているファイル type の ID 無効なノード用の ID nodes.h 0 EXECUTOR 関連 execnodes.h 10~ PLAN 関連 plannodes.h 100 番台 PLAN STATE 関連 execnodes.h 200 番台 PRIMITIVE 関連 primnodes.h 300 番台 EXPRESSION STATE 関連 execnodes.h 400 番台 PLANNER 関連 relation.h 500 番台 MEMORY 関連 memnodes.h 600~649 VALUE 関連 value.h 650~655 リスト関連 pg_list.h 656~658 PARSE TREE 関連 parsenodes.h 700 番台と 800 番台 FUNCTION-CALL CONTEXT と RESULTINFO 関連 fmgr.h 900~ EX ECUTOR 関連 のノードは 実行時にエグゼキュータが使用する PLAN 関連 は プラン木で使われるノードである PLAN STATE 関連 については 詳しく調べていないが エグゼキュータで使われるようである PRIMITIVE 関連 は クエリ木以降 プラン木までの間共通で使われるノードである EXPRESSION STATE 関連 のノードは どこで使われるか調べていない PLANNER 関連 のノードは パスツリーを作るのに使われる MEMORY 関連 のノードは クエリ処理とは少し系統が違って メモリコンテキストの木構造を作るのに使われる VALUE 関連 のノードは gram.y でクエリ中の定数を入れるためのノードを構築する際に使用される リスト関連 のノードは クエリ処理で使うリスト構造を構築するのに使われる 例えば 複数のパーズ木をつなぐためのリスト構造に使われる PARSE TREE 関連 のノードは パーズ木を構成するのに使われる PARSE TREE 関連 のノ 5/8

ードは type として 700 番台と 800 番台が使われる 700 番台は SQL の種類にあたるノードが定義されており 800 番台は各 SQL の構成要素に使われるノードが定義されている FUNCTION-CALL CONTEXT と RESULTINFO 関連 も今回は詳しく調べていないが トリガの実装とエグゼキュータあたりで使われるようである 2.2. ノード操作の関数 PostgreSQL では Node 型のデータおよびツリーを操作するために いくつかの関数が定義されている まず Node をサブツリーも含めてコピーする copy 関数群 (copyfuncs.c) Node をサブツリーごと比較するための equal 関数群 (equalfuncs.c) その他に デバッグ時に Node の内容を表示するための out 関数群 (outfuncs.c) である これらは それぞれ src/backend/nodes ディレクトリ以下のファイルとして実装されている 実装の方法もほとんど同じで 例えば copy を例に挙げると まず ローカルに _copyplan(plan *from) のような Plan 型用の関数が type の分だけ定義してある 呼び出し元は1 箇所で copyobject(void * from) である そして copyobject () 関数の先頭で nodetype をチェックして switch 文を使って 型に合わせたローカルなコピー関数を呼び出すようになっている 以下が copyobject の実際のコードである void * copyobject(void *from) void *retval; if (from == NULL) return NULL; switch (nodetag(from)) * PLAN NODES case T_Plan retval = _copyplan(from); break; case T_Result retval = _copyresult(from); break; _copyplan() や _copyresult() などの関数は copyfuncs.c ファイルの前の方で個別に定義してあり 構造体内のすべてのデータをコピーするように書いてある その過程で copyobject が再帰的に呼び出されるところも出てくる ここでは コピーを例に挙げて説明したが Node 型のオブジェクトを再帰的に表示させる outfuncs は ほぼ同じ作りである equalfuncs も引数が2つになることを除けば ほぼ同じ作りであると言える 6/8

2.3. ソースコードノード関連のソースコードは include/nodes と src/backend/nodes に分かれている include/nodes 以下には 各 type に対応する Node 型にキャストして読み取れる構造体を定義しているファイルと node 構造を支援する関数のヘッダという2 種類のファイルが存在する 2.3.1. include/nodes 以下のファイル ( ) のついているファイルには それぞれのフェーズで使われる Node 型に対応する構造体の定義が 書かれている bitmapset.h execnodes.h ( ) makefuncs.h memnodes.h ( ) nodefuncs.h nodes.h params.h parsenodes.h ( ) pg_list.h plannodes.h ( ) primnodes.h ( ) print.h readfuncs.h relation.h ( ) value.h ( ) bitmapset.c の外部宣言ファイル エグゼキュータで使われるノードの構造体を定義したファイル makefuncs.c の外部宣言ファイル メモリコンテキストで使うノードの構造体を定義したファイル nodefuncs.c の外部宣言ファイル NodeTag の enum 型を定義してあるファイル 他にも Node 型の定義や関数の外部宣言を含む プラン木のパラメータに使うデータ構造を定義したファイル パーザで使うノードの構造体を定義したファイル Node をリストとして操作するためのマクロパッケージ プランナで使われるノードの構造体を定義したファイル パーザ プランナ エグゼキュータで共通に使われるプリミティブなノードの構造を定義したファイル print.c の関数の外部宣言用ファイル readfuncs.c の関数の外部宣言用ファイル プランナで使用するノードの構造体を定義したファイル 定数としてもつ数値関連のノードの構造体を定義したファイル 2.3.2. src/backend/nodes 以下 node 構造を支援するための関数が定義されたファイルである bitmapset.c Plan ノードや PlanState ノードで使用するビットマップ配列の実装 copyfuncs.c Node 型をツリーとして再帰的にコピーするためのパッケージ equalfuncs.c Node 型をツリーとして再帰的に比較するためのパッケージ list.c リスト操作のための実装 ( マクロを除く ) makefuncs.c パーズ時にノードを生成するための関数群 nodefuncs.c ノード操作用の関数 nodes.c 変数が1つ定義されているだけで 関数は1つも定義されていない outfuncs.c Node 型を表示可能な文字列に再帰的に置き換えるパッケージ 7/8

params.c クエリプラン木のパラメータリストの支援関数 print.c ツリーの表示の実装 ( 主にデバッグ用 ) read.c ノード木を文字列で表現したものからトークンを取り出す readfuncs.c から呼び出される stringtonode() で 文字列をローカルな pg_strtok_ptr という変数に設定しておき pg_strtok() を呼び出すと そこからトークンを取り出す readfuncs.c ノード木を文字列で表現したものからノード木を再構築する outfuncs.c で生成した nodetostring() の結果からノード木を再構築できる パスツリーやプラン木に対して使われることはないため パスツリーやプラン木に対応するコードは実装されていない value.c 即値ノードの実装 主なものは パーズ木の生成に使われる makefuncs.c Node 型ツリーの比較に使われる equalfuncs.c Node 型ツリーのコピーに使われる copyfuncs.c Node 型ツリーを表示可能な文字列に置き換える outfuncs.c outfuncs.c で生成した文字列から Node 型ツリーを再構築する readfuncs.c などである <EOF> 8/8