]> granicus.if.org Git - postgresql/commitdiff
Fix hashjoin costing mistake introduced with inner_unique optimization.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Jul 2018 15:59:12 +0000 (11:59 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Jul 2018 15:59:12 +0000 (11:59 -0400)
In final_cost_hashjoin(), commit 9c7f5229a allowed inner_unique cases
to follow a code path previously used only for SEMI/ANTI joins; but it
neglected to fix an if-test within that path that assumed SEMI and ANTI
were the only possible cases.  This resulted in a wrong value for
hashjointuples, and an ensuing bad cost estimate, for inner_unique normal
joins.  Fortunately, for inner_unique normal joins we can assume the number
of joined tuples is the same as for a SEMI join; so there's no need for
more code, we just have to invert the test to check for ANTI not SEMI.

It turns out that in two contrib tests in which commit 9c7f5229a
changed the plan expected for a query, the change was actually wrong
and induced by this estimation error, not by any real improvement.
Hence this patch also reverts those changes.

Per report from RK Korlapati.  Backpatch to v10 where the error was
introduced.

David Rowley

Discussion: https://postgr.es/m/CA+SNy03bhq0fodsfOkeWDCreNjJVjsdHwUsb7AG=jpe0PtZc_g@mail.gmail.com

contrib/citext/expected/citext.out
contrib/citext/expected/citext_1.out
contrib/postgres_fdw/expected/postgres_fdw.out
src/backend/optimizer/path/costsize.c

index 95373182af5d8bbbb534a3d49f1f177329c626b6..99365c57b01bd61628e83382b4165dbc1472d88f 100644 (file)
@@ -2336,8 +2336,8 @@ SELECT *
   WHERE t.id IS NULL OR m.id IS NULL;
  id | name | id | name 
 ----+------+----+------
-  2 | two  |    | 
     |      |  2 | Two
+  2 | two  |    | 
 (2 rows)
 
 REFRESH MATERIALIZED VIEW CONCURRENTLY citext_matview;
index 855ec3f10b715e86343c74450ba9a6082f549bb9..8aac72e2268b48b3475c47ef36a61e0a54bcdbff 100644 (file)
@@ -2336,8 +2336,8 @@ SELECT *
   WHERE t.id IS NULL OR m.id IS NULL;
  id | name | id | name 
 ----+------+----+------
-  2 | two  |    | 
     |      |  2 | Two
+  2 | two  |    | 
 (2 rows)
 
 REFRESH MATERIALIZED VIEW CONCURRENTLY citext_matview;
index cf4863c5aa2a6e9b423e9e75425f0bbd4f9da1e4..1dd8e13f33159b3f9eb22a65fac0d04c2a2c83ad 100644 (file)
@@ -4233,18 +4233,21 @@ explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
 
 explain (verbose, costs off) select * from ft3 f, loct3 l
   where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
-                       QUERY PLAN                        
----------------------------------------------------------
- Nested Loop
+                         QUERY PLAN                          
+-------------------------------------------------------------
+ Hash Join
    Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
-   Join Filter: ((f.f3)::text = (l.f3)::text)
-   ->  Index Scan using loct3_f1_key on public.loct3 l
-         Output: l.f1, l.f2, l.f3
-         Index Cond: (l.f1 = 'foo'::text)
+   Inner Unique: true
+   Hash Cond: ((f.f3)::text = (l.f3)::text)
    ->  Foreign Scan on public.ft3 f
          Output: f.f1, f.f2, f.f3
          Remote SQL: SELECT f1, f2, f3 FROM public.loct3
-(9 rows)
+   ->  Hash
+         Output: l.f1, l.f2, l.f3
+         ->  Index Scan using loct3_f1_key on public.loct3 l
+               Output: l.f1, l.f2, l.f3
+               Index Cond: (l.f1 = 'foo'::text)
+(12 rows)
 
 -- ===================================================================
 -- test writable foreign table stuff
index a2a7e0c520228b7840fb2d1507179b6aec84bbc5..31ff618d8fb791aaaf535261feaa90c7360a2d6b 100644 (file)
@@ -3457,10 +3457,10 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
                        clamp_row_est(inner_path_rows / virtualbuckets) * 0.05;
 
                /* Get # of tuples that will pass the basic join */
-               if (path->jpath.jointype == JOIN_SEMI)
-                       hashjointuples = outer_matched_rows;
-               else
+               if (path->jpath.jointype == JOIN_ANTI)
                        hashjointuples = outer_path_rows - outer_matched_rows;
+               else
+                       hashjointuples = outer_matched_rows;
        }
        else
        {