親クエリに依存しない(親テーブルを参照しない)スカラーサブクエリは、1回だけ評価されますか、それとも各行に対して評価されますか?
SELECT /* ... */
FROM
t1
WHERE
parent = (
-- is this sq evaluated once?
SELECT
t2.id
FROM t2
WHERE t2.id = 10
)
またはCTEを使用する
WITH parent_id AS (
SELECT
t2.id
FROM t2
WHERE t2.id = 10
)
SELECT /* ... */
WHERE
parent = (
SELECT p.id FROM parent_id p -- is this sq evaluated once?
)
サブクエリ/ CTEが各行に対して評価されるという答えの場合、各行でCTEを結合すると、パフォーマンスが向上しますか?
WITH parent_id AS (
SELECT
t2.id
FROM t2
WHERE t2.id = 10
)
SELECT /* ... */
FROM
t1, parent_id
WHERE
parent = parent_id.id
また、EXPLAIN ANALYZE
から式が何回評価されたかを把握する方法はありますか?
注:例は任意であり、実際のシナリオを反映していないため、サブクエリを実行して既知のid
(10
)を見つけることは意味がないという事実を無視してください。
一度評価されます。
EXPLAIN ANALYZE
は、次のような行を表示します。
... InitPlan 1 (returns $0) -> Index Scan using t2_pkey on t2 (cost=0.29..5.31 rows=1 width=4) (actual time=0.024..0.025 rows=1 loops=1) Index Cond: (id = 10) ...
loops=1
は、サブプランが一度だけ評価されたことを示します。 マニュアル:
一部のクエリプランでは、サブプランノードが複数回実行される可能性があります。たとえば、内側のインデックススキャンは、上記のネストされたループプランの外側の行ごとに1回実行されます。このような場合、
loops
値はノードの実行の総数を報告します[...]
次のようなcorrelatedサブクエリを使用します。
SELECT *, (SELECT id FROM t2 WHERE id = t1.parent_id) AS t2_id
FROM t1;
(またはもっと便利なもの)loops=
n
、ここでn
は行数t1
です。