}
/*
- * Likewise, if we found anything usable, generate a BitmapHeapPath for
- * the most promising combination of join bitmap index paths. Note there
- * will be only one such path no matter how many join clauses are
- * available. (XXX is that good enough, or do we need to consider even
- * more paths for different subsets of possible join partners? Also,
- * should we add in restriction bitmap paths as well?)
+ * Likewise, if we found anything usable, generate BitmapHeapPaths for the
+ * most promising combinations of join bitmap index paths. Our strategy
+ * is to generate one such path for each distinct parameterization seen
+ * among the available bitmap index paths. This may look pretty
+ * expensive, but usually there won't be very many distinct
+ * parameterizations.
*/
if (bitjoinpaths != NIL)
{
- Path *bitmapqual;
- Relids required_outer;
- double loop_count;
- BitmapHeapPath *bpath;
+ List *path_outer;
+ List *all_path_outers;
+ ListCell *lc;
- bitmapqual = choose_bitmap_and(root, rel, bitjoinpaths);
- required_outer = get_bitmap_tree_required_outer(bitmapqual);
- loop_count = get_loop_count(root, required_outer);
- bpath = create_bitmap_heap_path(root, rel, bitmapqual,
- required_outer, loop_count);
- add_path(rel, (Path *) bpath);
+ /*
+ * path_outer holds the parameterization of each path in bitjoinpaths
+ * (to save recalculating that several times), while all_path_outers
+ * holds all distinct parameterization sets.
+ */
+ path_outer = all_path_outers = NIL;
+ foreach(lc, bitjoinpaths)
+ {
+ Path *path = (Path *) lfirst(lc);
+ Relids required_outer;
+ bool found = false;
+ ListCell *lco;
+
+ required_outer = get_bitmap_tree_required_outer(path);
+ path_outer = lappend(path_outer, required_outer);
+
+ /* Have we already seen this param set? */
+ foreach(lco, all_path_outers)
+ {
+ Relids existing_outers = (Relids) lfirst(lco);
+
+ if (bms_equal(existing_outers, required_outer))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ /* No, so add it to all_path_outers */
+ all_path_outers = lappend(all_path_outers, required_outer);
+ }
+ }
+
+ /* Now, for each distinct parameterization set ... */
+ foreach(lc, all_path_outers)
+ {
+ Relids max_outers = (Relids) lfirst(lc);
+ List *this_path_set;
+ Path *bitmapqual;
+ Relids required_outer;
+ double loop_count;
+ BitmapHeapPath *bpath;
+ ListCell *lcp;
+ ListCell *lco;
+
+ /* Identify all the bitmap join paths needing no more than that */
+ this_path_set = NIL;
+ forboth(lcp, bitjoinpaths, lco, path_outer)
+ {
+ Path *path = (Path *) lfirst(lcp);
+ Relids p_outers = (Relids) lfirst(lco);
+
+ if (bms_is_subset(p_outers, max_outers))
+ this_path_set = lappend(this_path_set, path);
+ }
+
+ /*
+ * Add in restriction bitmap paths, since they can be used
+ * together with any join paths.
+ */
+ this_path_set = list_concat(this_path_set, bitindexpaths);
+
+ /* Select best AND combination for this parameterization */
+ bitmapqual = choose_bitmap_and(root, rel, this_path_set);
+
+ /* And push that path into the mix */
+ required_outer = get_bitmap_tree_required_outer(bitmapqual);
+ loop_count = get_loop_count(root, required_outer);
+ bpath = create_bitmap_heap_path(root, rel, bitmapqual,
+ required_outer, loop_count);
+ add_path(rel, (Path *) bpath);
+ }
}
}
Index Cond: (unique1 = 1)
-> Nested Loop
Join Filter: (t1.ten = t3.ten)
- -> Index Scan using tenk1_hundred on tenk1 t2
- Index Cond: (t1.hundred = hundred)
+ -> Bitmap Heap Scan on tenk1 t2
+ Recheck Cond: (t1.hundred = hundred)
+ -> Bitmap Index Scan on tenk1_hundred
+ Index Cond: (t1.hundred = hundred)
-> Index Scan using tenk1_unique2 on tenk1 t3
Index Cond: (unique2 = t2.thousand)
-(9 rows)
+(11 rows)
explain (costs off)
select * from tenk1 t1 left join
Index Cond: (unique1 = 1)
-> Nested Loop
Join Filter: ((t1.ten + t2.ten) = t3.ten)
- -> Index Scan using tenk1_hundred on tenk1 t2
- Index Cond: (t1.hundred = hundred)
+ -> Bitmap Heap Scan on tenk1 t2
+ Recheck Cond: (t1.hundred = hundred)
+ -> Bitmap Index Scan on tenk1_hundred
+ Index Cond: (t1.hundred = hundred)
-> Index Scan using tenk1_unique2 on tenk1 t3
Index Cond: (unique2 = t2.thousand)
-(9 rows)
+(11 rows)
explain (costs off)
select count(*) from
tenk1 a join tenk1 b on a.unique1 = b.unique2
left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand
join int4_tbl on b.thousand = f1;
- QUERY PLAN
---------------------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------------------------------------------
Aggregate
-> Nested Loop Left Join
Join Filter: (a.unique2 = b.unique1)
-> Nested Loop
-> Nested Loop
-> Seq Scan on int4_tbl
- -> Index Scan using tenk1_thous_tenthous on tenk1 b
- Index Cond: (thousand = int4_tbl.f1)
+ -> Bitmap Heap Scan on tenk1 b
+ Recheck Cond: (thousand = int4_tbl.f1)
+ -> Bitmap Index Scan on tenk1_thous_tenthous
+ Index Cond: (thousand = int4_tbl.f1)
-> Index Scan using tenk1_unique1 on tenk1 a
Index Cond: (unique1 = b.unique2)
-> Index Only Scan using tenk1_thous_tenthous on tenk1 c
Index Cond: (thousand = a.thousand)
-(12 rows)
+(14 rows)
select count(*) from
tenk1 a join tenk1 b on a.unique1 = b.unique2