mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Make EXPLAIN ANALYZE report the numbers of rows rejected by filter steps.
This provides information about the numbers of tuples that were visited but not returned by table scans, as well as the numbers of join tuples that were considered and discarded within a join plan node. There is still some discussion going on about the best way to report counts for outer-join situations, but I think most of what's in the patch would not change if we revise that, so I'm going to go ahead and commit it as-is. Documentation changes to follow (they weren't in the submitted patch either). Marko Tiikkaja, reviewed by Marc Cousin, somewhat revised by Tom
This commit is contained in:
@ -13,7 +13,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeAgg.h"
|
||||
#include "executor/nodeAppend.h"
|
||||
#include "executor/nodeBitmapAnd.h"
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "commands/tablespace.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "parser/parse_clause.h"
|
||||
|
@ -77,7 +77,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/executor.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeAgg.h"
|
||||
#include "executor/nodeAppend.h"
|
||||
#include "executor/nodeBitmapAnd.h"
|
||||
|
@ -219,6 +219,8 @@ ExecScan(ScanState *node,
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
|
||||
/*
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
|
@ -22,6 +22,7 @@ BufferUsage pgBufferUsage;
|
||||
static void BufferUsageAccumDiff(BufferUsage *dst,
|
||||
const BufferUsage *add, const BufferUsage *sub);
|
||||
|
||||
|
||||
/* Allocate new instrumentation structure(s) */
|
||||
Instrumentation *
|
||||
InstrAlloc(int n, int instrument_options)
|
||||
@ -31,13 +32,14 @@ InstrAlloc(int n, int instrument_options)
|
||||
/* timer is always required for now */
|
||||
Assert(instrument_options & INSTRUMENT_TIMER);
|
||||
|
||||
/* initialize all fields to zeroes, then modify as needed */
|
||||
instr = palloc0(n * sizeof(Instrumentation));
|
||||
if (instrument_options & INSTRUMENT_BUFFERS)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
instr[i].needs_bufusage = true;
|
||||
instr[i].need_bufusage = true;
|
||||
}
|
||||
|
||||
return instr;
|
||||
@ -52,8 +54,8 @@ InstrStartNode(Instrumentation *instr)
|
||||
else
|
||||
elog(DEBUG2, "InstrStartNode called twice in a row");
|
||||
|
||||
/* initialize buffer usage per plan node */
|
||||
if (instr->needs_bufusage)
|
||||
/* save buffer usage totals at node entry, if needed */
|
||||
if (instr->need_bufusage)
|
||||
instr->bufusage_start = pgBufferUsage;
|
||||
}
|
||||
|
||||
@ -77,8 +79,8 @@ InstrStopNode(Instrumentation *instr, double nTuples)
|
||||
|
||||
INSTR_TIME_SET_ZERO(instr->starttime);
|
||||
|
||||
/* Adds delta of buffer usage to node's count. */
|
||||
if (instr->needs_bufusage)
|
||||
/* Add delta of buffer usage since entry to node's totals */
|
||||
if (instr->need_bufusage)
|
||||
BufferUsageAccumDiff(&instr->bufusage,
|
||||
&pgBufferUsage, &instr->bufusage_start);
|
||||
|
||||
@ -119,12 +121,12 @@ InstrEndLoop(Instrumentation *instr)
|
||||
instr->tuplecount = 0;
|
||||
}
|
||||
|
||||
/* dst += add - sub */
|
||||
static void
|
||||
BufferUsageAccumDiff(BufferUsage *dst,
|
||||
const BufferUsage *add,
|
||||
const BufferUsage *sub)
|
||||
{
|
||||
/* dst += add - sub */
|
||||
dst->shared_blks_hit += add->shared_blks_hit - sub->shared_blks_hit;
|
||||
dst->shared_blks_read += add->shared_blks_read - sub->shared_blks_read;
|
||||
dst->shared_blks_written += add->shared_blks_written - sub->shared_blks_written;
|
||||
|
@ -1204,6 +1204,8 @@ agg_retrieve_direct(AggState *aggstate)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(aggstate, 1);
|
||||
}
|
||||
|
||||
/* No more groups */
|
||||
@ -1354,6 +1356,8 @@ agg_retrieve_hash_table(AggState *aggstate)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(aggstate, 1);
|
||||
}
|
||||
|
||||
/* No more groups */
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeBitmapAnd.h"
|
||||
|
||||
|
||||
|
@ -278,6 +278,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
||||
if (!ExecQual(node->bitmapqualorig, econtext, false))
|
||||
{
|
||||
/* Fails recheck, so drop it and loop back for another */
|
||||
InstrCountFiltered2(node, 1);
|
||||
ExecClearTuple(slot);
|
||||
continue;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeBitmapIndexscan.h"
|
||||
#include "executor/nodeIndexscan.h"
|
||||
#include "miscadmin.h"
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeBitmapOr.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
|
@ -118,6 +118,8 @@ ExecGroup(GroupState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -179,6 +181,8 @@ ExecGroup(GroupState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "commands/tablespace.h"
|
||||
#include "executor/execdebug.h"
|
||||
#include "executor/hashjoin.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "executor/nodeHash.h"
|
||||
#include "executor/nodeHashjoin.h"
|
||||
#include "miscadmin.h"
|
||||
|
@ -325,7 +325,11 @@ ExecHashJoin(HashJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
break;
|
||||
|
||||
case HJ_FILL_OUTER_TUPLE:
|
||||
@ -360,6 +364,8 @@ ExecHashJoin(HashJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -397,6 +403,8 @@ ExecHashJoin(HashJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
break;
|
||||
|
||||
case HJ_NEED_NEW_BATCH:
|
||||
|
@ -96,7 +96,11 @@ IndexNext(IndexScanState *node)
|
||||
econtext->ecxt_scantuple = slot;
|
||||
ResetExprContext(econtext);
|
||||
if (!ExecQual(node->indexqualorig, econtext, false))
|
||||
continue; /* nope, so ask index for another one */
|
||||
{
|
||||
/* Fails recheck, so drop it and loop back for another */
|
||||
InstrCountFiltered2(node, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return slot;
|
||||
|
@ -505,6 +505,8 @@ MJFillOuter(MergeJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -544,6 +546,8 @@ MJFillInner(MergeJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -893,7 +897,11 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -214,6 +214,8 @@ ExecNestLoop(NestLoopState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -270,7 +272,11 @@ ExecNestLoop(NestLoopState *node)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
|
||||
/*
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
|
Reference in New Issue
Block a user