diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 7097eff9b114522b74b49816592b0933efaa28da..e604be31f9d741dc39835bd7c1526419d8034220 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -85,6 +85,8 @@ static void show_sort_group_keys(PlanState *planstate, const char *qlabel, List *ancestors, ExplainState *es); static void show_sort_info(SortState *sortstate, ExplainState *es); static void show_hash_info(HashState *hashstate, ExplainState *es); +static void show_tidbitmap_info(BitmapHeapScanState *planstate, + ExplainState *es); static void show_instrumentation_count(const char *qlabel, int which, PlanState *planstate, ExplainState *es); static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es); @@ -1250,7 +1252,13 @@ ExplainNode(PlanState *planstate, List *ancestors, if (((BitmapHeapScan *) plan)->bitmapqualorig) show_instrumentation_count("Rows Removed by Index Recheck", 2, planstate, es); - /* FALL THRU */ + show_scan_qual(plan->qual, "Filter", planstate, ancestors, es); + if (plan->qual) + show_instrumentation_count("Rows Removed by Filter", 1, + planstate, es); + if (es->analyze) + show_tidbitmap_info((BitmapHeapScanState *) planstate, es); + break; case T_SeqScan: case T_ValuesScan: case T_CteScan: @@ -1878,6 +1886,29 @@ show_hash_info(HashState *hashstate, ExplainState *es) } } +/* + * If it's EXPLAIN ANALYZE, show exact/lossy pages for a BitmapHeapScan node + */ +static void +show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) +{ + if (es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyLong("Exact Heap Blocks", planstate->exact_pages, es); + ExplainPropertyLong("Lossy Heap Blocks", planstate->lossy_pages, es); + } + else + { + appendStringInfoSpaces(es->str, es->indent * 2); + appendStringInfoString(es->str, "Heap Blocks:"); + if (planstate->exact_pages > 0) + appendStringInfo(es->str, " exact=%ld", planstate->exact_pages); + if (planstate->lossy_pages > 0) + appendStringInfo(es->str, " lossy=%ld", planstate->lossy_pages); + appendStringInfoChar(es->str, '\n'); + } +} + /* * If it's EXPLAIN ANALYZE, show instrumentation information for a plan node * diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 3d98c2335c17239b65fdba1d34b3ba0ebf7cba6c..1a8d4e51430b232d96080da14a3ecd781f2787d0 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -170,6 +170,11 @@ BitmapHeapNext(BitmapHeapScanState *node) */ bitgetpage(scan, tbmres); + if (tbmres->ntuples >= 0) + node->exact_pages++; + else + node->lossy_pages++; + /* * Set rs_cindex to first slot to examine */ @@ -553,6 +558,8 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) scanstate->tbm = NULL; scanstate->tbmiterator = NULL; scanstate->tbmres = NULL; + scanstate->exact_pages = 0; + scanstate->lossy_pages = 0; scanstate->prefetch_iterator = NULL; scanstate->prefetch_pages = 0; scanstate->prefetch_target = 0; diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 94ab0f2a93368dda4f3bf144a28a0bca20b317d9..a301a08fba9f1c532ce58a8ea8f2c7ea11511001 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1338,6 +1338,8 @@ typedef struct BitmapIndexScanState * tbm bitmap obtained from child index scan(s) * tbmiterator iterator for scanning current pages * tbmres current-page data + * exact_pages total number of exact pages retrieved + * lossy_pages total number of lossy pages retrieved * prefetch_iterator iterator for prefetching ahead of current page * prefetch_pages # pages prefetch iterator is ahead of current * prefetch_target target prefetch distance @@ -1350,6 +1352,8 @@ typedef struct BitmapHeapScanState TIDBitmap *tbm; TBMIterator *tbmiterator; TBMIterateResult *tbmres; + long exact_pages; + long lossy_pages; TBMIterator *prefetch_iterator; int prefetch_pages; int prefetch_target;