From dd57ab3694d1dd36ed554ac0726cac3b497dfb73 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Thu, 19 Dec 2013 12:13:49 +0400 Subject: [PATCH 1/4] initial --- src/backend/executor/nodeIndexscan.c | 48 ++++++++++++++++++++++++- src/backend/nodes/copyfuncs.c | 2 ++ src/backend/nodes/tidbitmap.c | 39 ++++++++++++++++++++ src/backend/optimizer/path/indxpath.c | 36 +++++++++++++++++++ src/backend/optimizer/plan/createplan.c | 34 ++++++++++++++---- src/backend/optimizer/plan/setrefs.c | 8 +++++ src/backend/optimizer/plan/subselect.c | 14 ++++++++ src/backend/optimizer/util/pathnode.c | 1 + src/include/nodes/execnodes.h | 3 ++ src/include/nodes/plannodes.h | 2 ++ src/include/nodes/relation.h | 1 + src/include/nodes/tidbitmap.h | 8 +++++ 12 files changed, 189 insertions(+), 7 deletions(-) diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index f1062f19f4..4a89f27e8d 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -54,6 +54,7 @@ IndexNext(IndexScanState *node) IndexScanDesc scandesc; HeapTuple tuple; TupleTableSlot *slot; + TIDBitmap *flttbm; /* * extract necessary information from index scan node @@ -72,11 +73,28 @@ IndexNext(IndexScanState *node) econtext = node->ss.ps.ps_ExprContext; slot = node->ss.ss_ScanTupleSlot; + if (node->BitmapFilterPlanState && node->BitmapFilter == NULL) + node->BitmapFilter = (TIDBitmap *) MultiExecProcNode(node->BitmapFilterPlanState); + + flttbm = node->BitmapFilter; + + Assert(flttbm == NULL || IsA(flttbm, TIDBitmap)); + /* * ok, now that we have what we need, fetch the next tuple. */ while ((tuple = index_getnext(scandesc, direction)) != NULL) { + TBMCheckResult fltres = TBMExists; + + if (flttbm) + { + fltres = tbm_check_tuple(flttbm, &scandesc->xs_ctup.t_self); + + if (fltres == TBMNotFound) + continue; + } + /* * Store the scanned tuple in the scan tuple slot of the scan state. * Note: we pass 'false' because tuples returned by amgetnext are @@ -91,7 +109,7 @@ IndexNext(IndexScanState *node) * If the index was lossy, we have to recheck the index quals using * the fetched tuple. */ - if (scandesc->xs_recheck) + if (scandesc->xs_recheck || fltres == TBMRecheck) { econtext->ecxt_scantuple = slot; ResetExprContext(econtext); @@ -184,6 +202,15 @@ ExecReScanIndexScan(IndexScanState *node) } node->iss_RuntimeKeysReady = true; + if (node->BitmapFilterPlanState) + { + if (node->BitmapFilter) + tbm_free(node->BitmapFilter); + node->BitmapFilter = NULL; + + ExecReScan(node->BitmapFilterPlanState); + } + /* reset index scan */ index_rescan(node->iss_ScanDesc, node->iss_ScanKeys, node->iss_NumScanKeys, @@ -421,6 +448,13 @@ ExecEndIndexScan(IndexScanState *node) index_endscan(indexScanDesc); if (indexRelationDesc) index_close(indexRelationDesc, NoLock); + if (node->BitmapFilterPlanState) + { + ExecEndNode(node->BitmapFilterPlanState); + + if (node->BitmapFilter) + tbm_free(node->BitmapFilter); + } /* * close the heap relation. @@ -527,6 +561,18 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); + if (node->bitmapfilterplan) + { + indexstate->BitmapFilterPlanState = + ExecInitNode(node->bitmapfilterplan, estate, + eflags & ~(EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)); + + elog(NOTICE, "TEODOR ExecInitIndexScan"); + } + else + indexstate->BitmapFilterPlanState = NULL; + indexstate->BitmapFilter = NULL; + /* * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop * here. This allows an index-advisor plugin to EXPLAIN a plan containing diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 3e102310c5..871b97600e 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -373,6 +373,7 @@ _copyIndexScan(const IndexScan *from) COPY_NODE_FIELD(indexorderby); COPY_NODE_FIELD(indexorderbyorig); COPY_SCALAR_FIELD(indexorderdir); + COPY_NODE_FIELD(bitmapfilterplan); return newnode; } @@ -398,6 +399,7 @@ _copyIndexOnlyScan(const IndexOnlyScan *from) COPY_NODE_FIELD(indexorderby); COPY_NODE_FIELD(indextlist); COPY_SCALAR_FIELD(indexorderdir); + COPY_NODE_FIELD(bitmapfilterplan); return newnode; } diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index 43628aceb4..09ac0f003d 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -1020,3 +1020,42 @@ tbm_comparator(const void *left, const void *right) return 1; return 0; } + +/* + * tbm_check_tuple - check existance of tuple in tidbitmap. + * return zero (TBMNotFound) if not, TBMRecheck if tuple exists + * and requires recheck (recheck flag set or lossy page) and + * TBMExists if tuple exists and doesn't require recheck + */ +TBMCheckResult +tbm_check_tuple(TIDBitmap *tbm, const ItemPointer tid) +{ + BlockNumber blk = ItemPointerGetBlockNumber(tid); + OffsetNumber off = ItemPointerGetOffsetNumber(tid); + PagetableEntry *page; + int wordnum, + bitnum; + + /* safety check to ensure we don't overrun bit array bounds */ + if (off < 1 || off > MAX_TUPLES_PER_PAGE) + elog(ERROR, "tuple offset out of range: %u", off); + + if (tbm_page_is_lossy(tbm, blk)) + return TBMRecheck; /* whole page is already marked */ + + page = tbm_get_pageentry(tbm, blk); + if (page->ischunk) + { + wordnum = bitnum = 0; + } + else + { + wordnum = WORDNUM(off - 1); + bitnum = BITNUM(off - 1); + } + + return ( page->words[wordnum] & ((bitmapword) 1 << bitnum) ) ? + ( (page->ischunk || page->recheck) ? TBMRecheck : TBMExists ) + : + TBMNotFound; +} diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 606734a122..3bb6811d16 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -335,11 +335,47 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) { Path *bitmapqual; BitmapHeapPath *bpath; + List *bfpaths = NIL; bitmapqual = choose_bitmap_and(root, rel, bitindexpaths); bpath = create_bitmap_heap_path(root, rel, bitmapqual, rel->lateral_relids, 1.0); add_path(rel, (Path *) bpath); + + foreach(lc, rel->pathlist) + { + IndexPath *ipath = (IndexPath*)lfirst(lc), + *newpath; + + if (!IsA(ipath, IndexPath)) + continue; + + if (ipath->indexorderbys == NIL && ipath->indexorderbycols == NIL) + continue; + + newpath = palloc(sizeof(*newpath)); + memcpy(newpath, ipath, sizeof(*newpath)); + newpath->bitmapfilter = bitmapqual; + + //XXX + newpath->path.startup_cost /= 2.0; + newpath->path.total_cost /= 2.0; + newpath->indextotalcost /= 2.0; + //newpath->path.startup_cost += bitmapqual->total_cost; + //newpath->path.total_cost += bitmapqual->total_cost; + //newpath->indextotalcost += bitmapqual->total_cost; + + bfpaths = lappend(bfpaths, newpath); + + elog(NOTICE,"TEODOR create_index_paths"); + } + + foreach(lc, bfpaths) + { + Path *bfpath = (Path*)lfirst(lc); + + add_path(rel, bfpath); + } } /* diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index f2c122d295..546980c99a 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -98,12 +98,14 @@ static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid); static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig, List *indexorderby, List *indexorderbyorig, - ScanDirection indexscandir); + ScanDirection indexscandir, + Plan *bitmapfilterplan); static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexorderby, List *indextlist, - ScanDirection indexscandir); + ScanDirection indexscandir, + Plan *bitmapfilterplan); static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig); @@ -1145,6 +1147,8 @@ create_indexscan_plan(PlannerInfo *root, List *fixed_indexquals; List *fixed_indexorderbys; ListCell *l; + Plan *filter_plan = NULL; + /* it should be a base rel... */ Assert(baserelid > 0); @@ -1252,6 +1256,18 @@ create_indexscan_plan(PlannerInfo *root, replace_nestloop_params(root, (Node *) indexorderbys); } + if (best_path->bitmapfilter) + { + List *bitmapqualorig; + List *indexquals; + List *indexECs; + + filter_plan = create_bitmap_subplan(root, best_path->bitmapfilter, + &bitmapqualorig, &indexquals, + &indexECs); + elog(NOTICE,"TEODOR create_indexscan_plan %p %p", best_path->bitmapfilter, filter_plan); + } + /* Finally ready to build the plan node */ if (indexonly) scan_plan = (Scan *) make_indexonlyscan(tlist, @@ -1261,7 +1277,8 @@ create_indexscan_plan(PlannerInfo *root, fixed_indexquals, fixed_indexorderbys, best_path->indexinfo->indextlist, - best_path->indexscandir); + best_path->indexscandir, + filter_plan); else scan_plan = (Scan *) make_indexscan(tlist, qpqual, @@ -1271,7 +1288,8 @@ create_indexscan_plan(PlannerInfo *root, stripped_indexquals, fixed_indexorderbys, indexorderbys, - best_path->indexscandir); + best_path->indexscandir, + filter_plan); copy_path_costsize(&scan_plan->plan, &best_path->path); @@ -3238,7 +3256,8 @@ make_indexscan(List *qptlist, List *indexqualorig, List *indexorderby, List *indexorderbyorig, - ScanDirection indexscandir) + ScanDirection indexscandir, + Plan *bitmapfilterplan) { IndexScan *node = makeNode(IndexScan); Plan *plan = &node->scan.plan; @@ -3255,6 +3274,7 @@ make_indexscan(List *qptlist, node->indexorderby = indexorderby; node->indexorderbyorig = indexorderbyorig; node->indexorderdir = indexscandir; + node->bitmapfilterplan = bitmapfilterplan; return node; } @@ -3267,7 +3287,8 @@ make_indexonlyscan(List *qptlist, List *indexqual, List *indexorderby, List *indextlist, - ScanDirection indexscandir) + ScanDirection indexscandir, + Plan *bitmapfilterplan) { IndexOnlyScan *node = makeNode(IndexOnlyScan); Plan *plan = &node->scan.plan; @@ -3283,6 +3304,7 @@ make_indexonlyscan(List *qptlist, node->indexorderby = indexorderby; node->indextlist = indextlist; node->indexorderdir = indexscandir; + node->bitmapfilterplan = bitmapfilterplan; return node; } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 333efc2712..1820c8c54d 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -460,12 +460,20 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) fix_scan_list(root, splan->indexorderby, rtoffset); splan->indexorderbyorig = fix_scan_list(root, splan->indexorderbyorig, rtoffset); + if (splan->bitmapfilterplan) + splan->bitmapfilterplan = set_plan_refs(root, + splan->bitmapfilterplan, + rtoffset); } break; case T_IndexOnlyScan: { IndexOnlyScan *splan = (IndexOnlyScan *) plan; + if (splan->bitmapfilterplan) + splan->bitmapfilterplan = set_plan_refs(root, + splan->bitmapfilterplan, + rtoffset); return set_indexonlyscan_references(root, splan, rtoffset); } break; diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 0f92118660..a1e9b5e2ca 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -2100,6 +2100,13 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, * indexorderbyorig. */ context.paramids = bms_add_members(context.paramids, scan_params); + if (((IndexScan *) plan)->bitmapfilterplan) + context.paramids = + bms_add_members(context.paramids, + finalize_plan(root, + (Plan *) ((IndexScan *) plan)->bitmapfilterplan, + valid_params, + scan_params)); break; case T_IndexOnlyScan: @@ -2112,6 +2119,13 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, * we need not look at indextlist, since it cannot contain Params. */ context.paramids = bms_add_members(context.paramids, scan_params); + if (((IndexOnlyScan *) plan)->bitmapfilterplan) + context.paramids = + bms_add_members(context.paramids, + finalize_plan(root, + (Plan *) ((IndexOnlyScan *) plan)->bitmapfilterplan, + valid_params, + scan_params)); break; case T_BitmapIndexScan: diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index a7169efd85..15b0899605 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -766,6 +766,7 @@ create_index_path(PlannerInfo *root, pathnode->indexorderbys = indexorderbys; pathnode->indexorderbycols = indexorderbycols; pathnode->indexscandir = indexscandir; + pathnode->bitmapfilter = NULL; cost_index(pathnode, root, loop_count); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 5a4034729c..800f8c5d32 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1260,6 +1260,8 @@ typedef struct IndexScanState ExprContext *iss_RuntimeContext; Relation iss_RelationDesc; IndexScanDesc iss_ScanDesc; + PlanState *BitmapFilterPlanState; + TIDBitmap *BitmapFilter; } IndexScanState; /* ---------------- @@ -1296,6 +1298,7 @@ typedef struct IndexOnlyScanState IndexScanDesc ioss_ScanDesc; Buffer ioss_VMBuffer; long ioss_HeapFetches; + Node *BitmapFilter; } IndexOnlyScanState; /* ---------------- diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 101e22cee1..33924dc2df 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -313,6 +313,7 @@ typedef struct IndexScan List *indexorderby; /* list of index ORDER BY exprs */ List *indexorderbyorig; /* the same in original form */ ScanDirection indexorderdir; /* forward or backward or don't care */ + Plan *bitmapfilterplan; } IndexScan; /* ---------------- @@ -340,6 +341,7 @@ typedef struct IndexOnlyScan List *indexorderby; /* list of index ORDER BY exprs */ List *indextlist; /* TargetEntry list describing index's cols */ ScanDirection indexorderdir; /* forward or backward or don't care */ + Plan *bitmapfilterplan; } IndexOnlyScan; /* ---------------- diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 6d7b5948cd..dd3b0888d5 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -796,6 +796,7 @@ typedef struct IndexPath ScanDirection indexscandir; Cost indextotalcost; Selectivity indexselectivity; + Path *bitmapfilter; /* IndexPath, BitmapAndPath or BitmapOrPath */ } IndexPath; /* diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h index 70c0025f97..406c33e3d6 100644 --- a/src/include/nodes/tidbitmap.h +++ b/src/include/nodes/tidbitmap.h @@ -63,4 +63,12 @@ extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm); extern TBMIterateResult *tbm_iterate(TBMIterator *iterator); extern void tbm_end_iterate(TBMIterator *iterator); +typedef enum { + TBMNotFound = 0, + TBMExists, + TBMRecheck +} TBMCheckResult; + +extern TBMCheckResult tbm_check_tuple(TIDBitmap *tbm, const ItemPointer tid); + #endif /* TIDBITMAP_H */ From 1e71f8b74a63f9b91cd14b5c53e9a6bab67bddb4 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Thu, 19 Dec 2013 16:10:41 +0400 Subject: [PATCH 2/4] some explain --- src/backend/commands/explain.c | 6 +++ src/backend/executor/nodeIndexonlyscan.c | 48 +++++++++++++++++++++++- src/include/nodes/execnodes.h | 3 +- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 9969a251a7..c973df656c 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1223,6 +1223,9 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); + if (((IndexScan *) plan)->bitmapfilterplan) + ExplainNode(((IndexScanState *) planstate)->BitmapFilterPlanState, + ancestors, "Bitmap filter", NULL, es); break; case T_IndexOnlyScan: show_scan_qual(((IndexOnlyScan *) plan)->indexqual, @@ -1239,6 +1242,9 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->analyze) ExplainPropertyLong("Heap Fetches", ((IndexOnlyScanState *) planstate)->ioss_HeapFetches, es); + if (((IndexOnlyScan *) plan)->bitmapfilterplan) + ExplainNode(((IndexOnlyScanState *) planstate)->BitmapFilterPlanState, + ancestors, "Bitmap filter", NULL, es); break; case T_BitmapIndexScan: show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig, diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 2f30c55c54..9c36eda683 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -55,6 +55,7 @@ IndexOnlyNext(IndexOnlyScanState *node) IndexScanDesc scandesc; TupleTableSlot *slot; ItemPointer tid; + TIDBitmap *flttbm; /* * extract necessary information from index scan node @@ -73,12 +74,28 @@ IndexOnlyNext(IndexOnlyScanState *node) econtext = node->ss.ps.ps_ExprContext; slot = node->ss.ss_ScanTupleSlot; + if (node->BitmapFilterPlanState && node->BitmapFilter == NULL) + node->BitmapFilter = (TIDBitmap *) MultiExecProcNode(node->BitmapFilterPlanState); + + flttbm = node->BitmapFilter; + + Assert(flttbm == NULL || IsA(flttbm, TIDBitmap)); + /* * OK, now that we have what we need, fetch the next tuple. */ while ((tid = index_getnext_tid(scandesc, direction)) != NULL) { HeapTuple tuple = NULL; + TBMCheckResult fltres = TBMExists; + + if (flttbm) + { + fltres = tbm_check_tuple(flttbm, &scandesc->xs_ctup.t_self); + + if (fltres == TBMNotFound) + continue; + } /* * We can skip the heap fetch if the TID references a heap page on @@ -137,7 +154,7 @@ IndexOnlyNext(IndexOnlyScanState *node) * (Currently, this can never happen, but we should support the case * for possible future use, eg with GiST indexes.) */ - if (scandesc->xs_recheck) + if (scandesc->xs_recheck || fltres == TBMRecheck) { econtext->ecxt_scantuple = slot; ResetExprContext(econtext); @@ -266,6 +283,15 @@ ExecReScanIndexOnlyScan(IndexOnlyScanState *node) } node->ioss_RuntimeKeysReady = true; + if (node->BitmapFilterPlanState) + { + if (node->BitmapFilter) + tbm_free(node->BitmapFilter); + node->BitmapFilter = NULL; + + ExecReScan(node->BitmapFilterPlanState); + } + /* reset index scan */ index_rescan(node->ioss_ScanDesc, node->ioss_ScanKeys, node->ioss_NumScanKeys, @@ -323,6 +349,14 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) if (indexRelationDesc) index_close(indexRelationDesc, NoLock); + if (node->BitmapFilterPlanState) + { + ExecEndNode(node->BitmapFilterPlanState); + + if (node->BitmapFilter) + tbm_free(node->BitmapFilter); + } + /* * close the heap relation. */ @@ -431,6 +465,18 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); + if (node->bitmapfilterplan) + { + indexstate->BitmapFilterPlanState = + ExecInitNode(node->bitmapfilterplan, estate, + eflags & ~(EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)); + + elog(NOTICE, "TEODOR ExecInitIndexOnlyScan"); + } + else + indexstate->BitmapFilterPlanState = NULL; + indexstate->BitmapFilter = NULL; + /* * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop * here. This allows an index-advisor plugin to EXPLAIN a plan containing diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 800f8c5d32..865e0e8d35 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1298,7 +1298,8 @@ typedef struct IndexOnlyScanState IndexScanDesc ioss_ScanDesc; Buffer ioss_VMBuffer; long ioss_HeapFetches; - Node *BitmapFilter; + PlanState *BitmapFilterPlanState; + TIDBitmap *BitmapFilter; } IndexOnlyScanState; /* ---------------- From 628027035a3b7fd892547941f4ab78dbc3cf6578 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Fri, 20 Dec 2013 11:15:23 +0400 Subject: [PATCH 3/4] explain --- src/backend/optimizer/path/costsize.c | 1 + src/backend/optimizer/path/indxpath.c | 7 +++++++ src/backend/tcop/postgres.c | 3 +++ src/backend/utils/misc/guc.c | 9 +++++++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/optimizer/cost.h | 1 + src/test/regress/expected/rangefuncs.out | 3 ++- 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 50f08521bf..885661d62c 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -110,6 +110,7 @@ bool enable_seqscan = true; bool enable_indexscan = true; bool enable_indexonlyscan = true; bool enable_bitmapscan = true; +bool enable_bitmapfilter = true; bool enable_tidscan = true; bool enable_sort = true; bool enable_hashagg = true; diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 3bb6811d16..29e724395d 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -365,6 +365,13 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) //newpath->path.total_cost += bitmapqual->total_cost; //newpath->indextotalcost += bitmapqual->total_cost; + if (enable_bitmapfilter) + { + newpath->path.startup_cost += disable_cost; + newpath->path.total_cost += disable_cost; + newpath->indextotalcost += disable_cost; + } + bfpaths = lappend(bfpaths, newpath); elog(NOTICE,"TEODOR create_index_paths"); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index e6428b69f4..fdf76c2d8f 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3201,6 +3201,9 @@ set_plan_disabling_options(const char *arg, GucContext context, GucSource source case 'b': /* bitmapscan */ tmp = "enable_bitmapscan"; break; + case 'f': /* bitmapfilter */ + tmp = "enable_bitmapfilter"; + break; case 't': /* tidscan */ tmp = "enable_tidscan"; break; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 51416f49cd..5ee6ec6f09 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -705,6 +705,15 @@ static struct config_bool ConfigureNamesBool[] = true, NULL, NULL, NULL }, + { + {"enable_bitmapfilter", PGC_USERSET, QUERY_TUNING_METHOD, + gettext_noop("Enables the planner's use of bitmap-filtering in index scan."), + NULL + }, + &enable_bitmapfilter, + true, + NULL, NULL, NULL + }, { {"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD, gettext_noop("Enables the planner's use of TID scan plans."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index d049159444..ce809a7d9c 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -261,6 +261,7 @@ # - Planner Method Configuration - #enable_bitmapscan = on +#enable_bitmapfilter = on #enable_hashagg = on #enable_hashjoin = on #enable_indexscan = on diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 444ab74044..355eb6730b 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -54,6 +54,7 @@ extern bool enable_seqscan; extern bool enable_indexscan; extern bool enable_indexonlyscan; extern bool enable_bitmapscan; +extern bool enable_bitmapfilter; extern bool enable_tidscan; extern bool enable_sort; extern bool enable_hashagg; diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index a988dd01a1..8c88dda13e 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -1,6 +1,7 @@ SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%'; name | setting ----------------------+--------- + enable_bitmapfilter | on enable_bitmapscan | on enable_hashagg | on enable_hashjoin | on @@ -12,7 +13,7 @@ SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%'; enable_seqscan | on enable_sort | on enable_tidscan | on -(11 rows) +(12 rows) CREATE TABLE foo2(fooid int, f2 int); INSERT INTO foo2 VALUES(1, 11); From 2db0a451bb234a2e539fc9ef1abd4f075883de54 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Fri, 20 Dec 2013 17:16:18 +0400 Subject: [PATCH 4/4] cost --- src/backend/optimizer/path/costsize.c | 41 +++++++++++++++++++++++++++ src/backend/optimizer/path/indxpath.c | 15 +--------- src/include/optimizer/cost.h | 1 + 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 885661d62c..8ff74c17f8 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -457,6 +457,47 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count) path->path.total_cost = startup_cost + run_cost; } +/* + * Tweaks cost estimation of index scan with bitmap filter + */ +void +cost_filtered_index(IndexPath *path) +{ + Path *bitmapqual = path->bitmapfilter; + double rows; + Cost reducedFilterCost; + Selectivity selec = 0; + + if (IsA(path, IndexPath)) + selec = ((IndexPath *) bitmapqual)->indexselectivity; + else if (IsA(path, BitmapAndPath)) + selec = ((BitmapAndPath *) bitmapqual)->bitmapselectivity; + else if (IsA(path, BitmapOrPath)) + selec = ((BitmapOrPath *) bitmapqual)->bitmapselectivity; + else + elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual)); + + rows = path->path.rows * selec; + reducedFilterCost = rows * cpu_operator_cost; + + + //XXX + path->path.startup_cost /= 2.0; + path->path.total_cost /= 2.0; + path->indextotalcost /= 2.0; + + //path->path.startup_cost += bitmapqual->total_cost; + //path->path.total_cost += bitmapqual->total_cost - reducedFilterCost; + //path->indextotalcost += bitmapqual->total_cost - reducedFilterCost; + + if (enable_bitmapfilter == false) + { + path->path.startup_cost += disable_cost; + path->path.total_cost += disable_cost; + path->indextotalcost += disable_cost; + } +} + void set_default_effective_cache_size(void) { diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 29e724395d..5a010423d0 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -357,20 +357,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) memcpy(newpath, ipath, sizeof(*newpath)); newpath->bitmapfilter = bitmapqual; - //XXX - newpath->path.startup_cost /= 2.0; - newpath->path.total_cost /= 2.0; - newpath->indextotalcost /= 2.0; - //newpath->path.startup_cost += bitmapqual->total_cost; - //newpath->path.total_cost += bitmapqual->total_cost; - //newpath->indextotalcost += bitmapqual->total_cost; - - if (enable_bitmapfilter) - { - newpath->path.startup_cost += disable_cost; - newpath->path.total_cost += disable_cost; - newpath->indextotalcost += disable_cost; - } + cost_filtered_index(newpath); bfpaths = lappend(bfpaths, newpath); diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 355eb6730b..031d7f36bb 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -71,6 +71,7 @@ extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info); extern void cost_index(IndexPath *path, PlannerInfo *root, double loop_count); +extern void cost_filtered_index(IndexPath *path); extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count);