*** a/src/backend/commands/explain.c --- b/src/backend/commands/explain.c *************** *** 81,86 **** static void show_sort_keys_common(PlanState *planstate, --- 81,87 ---- 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_heap_pages(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); *************** *** 1246,1251 **** ExplainNode(PlanState *planstate, List *ancestors, --- 1247,1254 ---- if (((BitmapHeapScan *) plan)->bitmapqualorig) show_instrumentation_count("Rows Removed by Index Recheck", 2, planstate, es); + if (es->analyze) + show_heap_pages((BitmapHeapScanState *) planstate, es); /* FALL THRU */ case T_SeqScan: case T_ValuesScan: *************** *** 1814,1819 **** show_hash_info(HashState *hashstate, ExplainState *es) --- 1817,1845 ---- } /* + * If it's EXPLAIN ANALYZE, show heap page fetches for a BitmapHeapScan node + */ + static void + show_heap_pages(BitmapHeapScanState *planstate, ExplainState *es) + { + if (es->format == EXPLAIN_FORMAT_TEXT) + { + 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'); + } + else + { + ExplainPropertyLong("Exact Heap Blocks", planstate->exact_pages, es); + ExplainPropertyLong("Lossy Heap Blocks", planstate->lossy_pages, es); + } + } + + /* * If it's EXPLAIN ANALYZE, show instrumentation information for a plan node * * "which" identifies which instrumentation counter to print *** a/src/backend/executor/nodeBitmapHeapscan.c --- b/src/backend/executor/nodeBitmapHeapscan.c *************** *** 170,175 **** BitmapHeapNext(BitmapHeapScanState *node) --- 170,180 ---- */ bitgetpage(scan, tbmres); + if (tbmres->ntuples >= 0) + node->exact_pages++; + else + node->lossy_pages++; + /* * Set rs_cindex to first slot to examine */ *************** *** 556,561 **** ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) --- 561,568 ---- scanstate->prefetch_iterator = NULL; scanstate->prefetch_pages = 0; scanstate->prefetch_target = 0; + scanstate->exact_pages = 0; + scanstate->lossy_pages = 0; /* * Miscellaneous initialization *** a/src/include/nodes/execnodes.h --- b/src/include/nodes/execnodes.h *************** *** 1352,1357 **** typedef struct BitmapHeapScanState --- 1352,1359 ---- TBMIterator *prefetch_iterator; int prefetch_pages; int prefetch_target; + long exact_pages; + long lossy_pages; } BitmapHeapScanState; /* ----------------