You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Optimize joins when the inner relation can be proven unique.
If there can certainly be no more than one matching inner row for a given
outer row, then the executor can move on to the next outer row as soon as
it's found one match; there's no need to continue scanning the inner
relation for this outer row. This saves useless scanning in nestloop
and hash joins. In merge joins, it offers the opportunity to skip
mark/restore processing, because we know we have not advanced past the
first possible match for the next outer row.
Of course, the devil is in the details: the proof of uniqueness must
depend only on joinquals (not otherquals), and if we want to skip
mergejoin mark/restore then it must depend only on merge clauses.
To avoid adding more planning overhead than absolutely necessary,
the present patch errs in the conservative direction: there are cases
where inner_unique or skip_mark_restore processing could be used, but
it will not do so because it's not sure that the uniqueness proof
depended only on "safe" clauses. This could be improved later.
David Rowley, reviewed and rather heavily editorialized on by me
Discussion: https://postgr.es/m/CAApHDvqF6Sw-TK98bW48TdtFJ+3a7D2mFyZ7++=D-RyPsL76gw@mail.gmail.com
@@ -1854,12 +1859,10 @@ SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1)
1854
1859
-> Foreign Scan on public.ft1 t1
1855
1860
Output: t1.c1
1856
1861
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1857
-
-> Materialize
1862
+
-> Foreign Scan on public.ft2 t2
1858
1863
Output: t2.c1
1859
-
-> Foreign Scan on public.ft2 t2
1860
-
Output: t2.c1
1861
-
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1862
-
(13 rows)
1864
+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1865
+
(11 rows)
1863
1866
1864
1867
SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1865
1868
c1
@@ -1889,12 +1892,10 @@ SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2
1889
1892
-> Foreign Scan on public.ft1 t1
1890
1893
Output: t1.c1
1891
1894
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1892
-
-> Materialize
1895
+
-> Foreign Scan on public.ft2 t2
1893
1896
Output: t2.c2
1894
-
-> Foreign Scan on public.ft2 t2
1895
-
Output: t2.c2
1896
-
Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1897
-
(13 rows)
1897
+
Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1898
+
(11 rows)
1898
1899
1899
1900
SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1900
1901
c1
@@ -3121,6 +3122,7 @@ select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x w
3121
3122
Group Key: x.b
3122
3123
-> Hash Join
3123
3124
Output: x.b
3125
+
Inner Unique: true
3124
3126
Hash Cond: (ft1.c2 = x.a)
3125
3127
-> Foreign Scan on public.ft1
3126
3128
Output: ft1.c2
@@ -3133,7 +3135,7 @@ select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x w
3133
3135
Output: ft1_1.c2, (sum(ft1_1.c1))
3134
3136
Relations: Aggregate on (public.ft1)
3135
3137
Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY c2
3136
-
(20 rows)
3138
+
(21 rows)
3137
3139
3138
3140
select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2;
3139
3141
count | b
@@ -3252,6 +3254,7 @@ select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.
3252
3254
Output: sum(q.a), count(q.b)
3253
3255
-> Nested Loop Left Join
3254
3256
Output: q.a, q.b
3257
+
Inner Unique: true
3255
3258
Join Filter: ((ft4.c1)::numeric <= q.b)
3256
3259
-> Foreign Scan on public.ft4
3257
3260
Output: ft4.c1, ft4.c2, ft4.c3
@@ -3264,7 +3267,7 @@ select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.
3264
3267
Output: 13, (avg(ft1.c1)), NULL::bigint
3265
3268
Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
3266
3269
Remote SQL: SELECT 13, avg(r1."C 1"), NULL::bigint FROM ("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
3267
-
(16 rows)
3270
+
(17 rows)
3268
3271
3269
3272
select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b);
3270
3273
sum | count
@@ -4048,20 +4051,18 @@ explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
4048
4051
4049
4052
explain (verbose, costs off) select * from ft3 f, loct3 l
4050
4053
where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
0 commit comments