]> 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 9cc94f4c1bdea89d058bdf8097ef962302e555cc..bc5d92eb9178fff1f0072d994732d92a00b1c95f 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 d1fb1e14e02e4abf97fe8541eba8535409987521..3d02d06b9c3967e6ffff0f58045e5c4687825657 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 9c0328eb63cd08ab5ad346a20d6cd5dee30d8e6c..f6bb2fc472cdf5dbfc6c492bae1c5a1a0bb20614 100644 (file)
@@ -4226,18 +4226,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 0cb9a88790f564646e47dcbd0f67988cbf5f59bb..7f867530d47caff6c2987b7a77eaebf6892480eb 100644 (file)
@@ -3180,10 +3180,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
        {