improve_bitmap_cost_v2.patch
application/octet-stream
Filename: improve_bitmap_cost_v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/nodes/tidbitmap.c | 24 | 4 |
| src/backend/optimizer/path/costsize.c | 38 | 0 |
| src/include/nodes/tidbitmap.h | 1 | 0 |
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index c4e53ad..6689c63 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -295,10 +295,7 @@ tbm_create(long maxbytes, dsa_area *dsa)
* for our purpose. Also count an extra Pointer per entry for the arrays
* created during iteration readout.
*/
- nbuckets = maxbytes /
- (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer));
- nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */
- nbuckets = Max(nbuckets, 16); /* sanity limit */
+ nbuckets = tbm_calculate_entires(maxbytes);
tbm->maxentries = (int) nbuckets;
tbm->lossify_start = 0;
tbm->dsa = dsa;
@@ -1562,3 +1559,26 @@ pagetable_free(pagetable_hash *pagetable, void *pointer)
tbm->dsapagetableold = InvalidDsaPointer;
}
}
+
+/*
+ * tbm_calculate_entires
+ *
+ * Calculate the number of estimated entries in the bitmap for given memory
+ * in bytes.
+ */
+long
+tbm_calculate_entires(double maxbytes)
+{
+ long nbuckets;
+
+ /*
+ * Estimate number of hashtable entries we can have within maxbytes. This
+ * estimates the hash cost as sizeof(PagetableEntry).
+ */
+ nbuckets = maxbytes /
+ (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer));
+ nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */
+ nbuckets = Max(nbuckets, 16); /* sanity limit */
+
+ return nbuckets;
+}
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 051a854..5b15f54 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -5132,6 +5132,10 @@ compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual,
double T;
double pages_fetched;
double tuples_fetched;
+ double heap_pages = 0;
+ double exact_pages = 0;
+ double lossy_pages = 0;
+ long maxentries;
/*
* Fetch total cost of obtaining the bitmap, as well as its total
@@ -5176,8 +5180,42 @@ compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual,
else
pages_fetched = ceil(pages_fetched);
+ /*
+ * Calculate the number of pages fetched from the heap. Then based on
+ * current work_mem estimate get the estimated maxentries in the bitmap.
+ */
+ heap_pages = Min(pages_fetched, baserel->pages);
+ maxentries = tbm_calculate_entires(work_mem * 1024L);
+
+ /*
+ * After the initial lossification that is maxentries / 2, the number of
+ * lossy pages grows slower. It is good enough to reflect this initial
+ * sharp increase in the lossy page number.
+ */
+ lossy_pages = Max(0, heap_pages - maxentries / 2);
+ exact_pages = heap_pages - lossy_pages;
+
+ /*
+ * If there are lossy pages then recompute the number of tuples processed
+ * by the bitmap heap node. For the exact_pages it's baserel->tuples *
+ * indexSelectivity and for lossy_pages we have to process all the tuples.
+ */
+ if (exact_pages > 0 && lossy_pages)
+ tuples_fetched = clamp_row_est (indexSelectivity *
+ (exact_pages / heap_pages) * baserel->tuples +
+ (lossy_pages / heap_pages) * baserel->tuples);
+
if (cost)
+ {
*cost = indexTotalCost;
+
+ /*
+ * If exact_pages are -ve then even after lossifying we will not be
+ * able to fit them into work_mem. Hence, disable this path.
+ */
+ if (exact_pages < 0)
+ *cost += disable_cost;
+ }
if (tuple)
*tuple = tuples_fetched;
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index f9a1902..1a8d9fc 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -70,5 +70,6 @@ extern void tbm_end_iterate(TBMIterator *iterator);
extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
dsa_pointer dp);
+extern long tbm_calculate_entires(double maxbytes);
#endif /* TIDBITMAP_H */