現在、AXLEプロジェクトの行レベルのセキュリティに関する作業の一環として、PostgreSQLパーサー、クエリリライター、クエリプランナーについて詳しく調べています。全体的な構造とフローに関する優れたドキュメントがいくつかあることに気付いたので、もっと紛らわしいコーナーのいくつかについて投稿し始めると思った詳細についてはあまり説明していません。
PostgreSQLのソースコードとその内部動作に興味がない場合は、今すぐ読むのをやめることができます。
resjunk
今日のトピックは、 resjunkを指す「resjunk」という用語です。 target-list属性。この用語は、プランナーとリライター全体で、通常は想定される知識として表示されます。名前はあまり役に立ちません。
resjunk 列については、 src / backend / executeor / execJunk.cで説明されています。 、適度に詳細なコメントがあります。ただし、包括的なアイデアを実際に説明しているわけではありません。
コンセプト つまり、PostgreSQLは、クエリ出力の一部ではないタプルごとの情報を追跡する必要がある場合があります。選択リストに含まれていない並べ替えキー、フィルターとして使用されて破棄されたサブクエリの中間結果、または ctidのような内部列の場合があります。 ユーザーには公開されません。
プランノードにはターゲットリストがあります。これらは、そのプランノードによって出力される列のリストです。単純なSELECTa、bFROMテストの場合 列a およびb クエリのインデックスまたはseqscanプランノードのターゲットリストに表示されます。次のトリミングされた出力に従って、プランロギングを有効にすることで、これを自分で観察できます。
regress=> CREATE TABLE
regress=> SET enable_print_plan = on;
regress=> SET client_min_messages = debug;
regress=> SELECT a, b FROM test;
LOG: plan:
DETAIL: {PLANNEDSTMT
:commandType 1
:queryId 0
....
:planTree
{SEQSCAN
:startup_cost 0.00
:total_cost 29.40
:plan_rows 1940
:plan_width 12
:targetlist (
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 1
...
:location 7
}
...
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 2
...
:location 10
}
....
:resjunk false
}
)
:qual
:lefttree
:righttree
:initPlan
:extParam (b)
:allParam (b)
:scanrelid 1
}
:rtable (
{RTE
:alias
:eref
{ALIAS
:aliasname test
:colnames ("a" "b")
}
...
:selectedCols (b 9 10)
:modifiedCols (b)
}
)
....
}
これが詳細な計画です:
QUERY PLAN -------------------------------------------------------- Seq Scan on test (cost=0.00..29.40 rows=1940 width=8)
その中に、 SELECTが表示されます。 ターゲットリストに2つのエントリがあり、各列に1つずつあります。 resjunkでもありません どちらもクエリによって出力されるためです。
列で並べ替えを追加するとどうなりますかc 、 SELECTには含まれていません -リスト、ターゲットリストに追加され、resjunkとしてマークされた新しい列が表示されます:
regress=> SELECT a, b FROM test ORDER BY c;
LOG: plan:
DETAIL: {PLANNEDSTMT
:commandType 1
....
:planTree
{SORT
....
:targetlist (
{TARGETENTRY
:expr
{VAR
:varno 65001
:varattno 1
...
}
:resno 1
:resname a
...
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 65001
:varattno 2
...
}
:resno 2
:resname b
....
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 65001
:varattno 3
...
}
:resno 3
:resname
....
:resjunk true
}
)
:qual
:lefttree
{SEQSCAN
...
:targetlist (
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 1
...
}
:resno 1
...
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 2
...
}
:resno 2
...
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 3
...
}
:resno 3
...
:resjunk true
}
)
....
}
:rtable (
{RTE
:alias
:eref
{ALIAS
:aliasname test
:colnames ("a" "b" "c")
}
....
:selectedCols (b 9 10 11)
:modifiedCols (b)
}
)
....
}
クエリプランの場合:
QUERY PLAN --------------------------------------------------------------- Sort (cost=135.34..140.19 rows=1940 width=12) Sort Key: c -> Seq Scan on test (cost=0.00..29.40 rows=1940 width=12) (3 rows)
つまり、 c resjunkとマークされています これは、最終的な計画の出力の一部ではない並べ替えキーだからです。
ctidも表示されます resjunkとマークされています UPDATEで およびDELETE 同様の理由でプラン–プランの読み取り部分は、変更する行とそのタプルIDをフェッチします。これらは最も外側のMODIFYTABLEに引き込まれます 行を更新して削除済みのマークを付け、更新の場合は新しいバージョンの行を挿入するプランノード。
これらの結果につながる研究は、助成金契約番号318633に基づいて欧州連合の第7フレームワークプログラム(FP7 / 2007-2013)から資金提供を受けています