]> 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 8c58720df6fbcc1267f3bae09184961af4a8dac6..fc2c51c9d044d28c101a6648a951d366118a2057 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 a6811e0338487babe2b7e01ebe4073af8491c7f4..7bf67a05295e042afac08560498205ce6297a597 100644 (file)
@@ -3454,10 +3454,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
        {