mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Rearrange the implementation of index-only scans.
This commit changes index-only scans so that data is read directly from the index tuple without first generating a faux heap tuple. The only immediate benefit is that indexes on system columns (such as OID) can be used in index-only scans, but this is necessary infrastructure if we are ever to support index-only scans on expression indexes. The executor is now ready for that, though the planner still needs substantial work to recognize the possibility. To do this, Vars in index-only plan nodes have to refer to index columns not heap columns. I introduced a new special varno, INDEX_VAR, to mark such Vars to avoid confusion. (In passing, this commit renames the two existing special varnos to OUTER_VAR and INNER_VAR.) This allows ruleutils.c to handle them with logic similar to what we use for subplan reference Vars. Since index-only scans are now fundamentally different from regular indexscans so far as their expression subtrees are concerned, I also chose to change them to have their own plan node type (and hence, their own executor source file).
This commit is contained in:
@ -79,6 +79,8 @@ static void show_instrumentation_count(const char *qlabel, int which,
|
||||
PlanState *planstate, ExplainState *es);
|
||||
static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es);
|
||||
static const char *explain_get_index_name(Oid indexId);
|
||||
static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
|
||||
ExplainState *es);
|
||||
static void ExplainScanTarget(Scan *plan, ExplainState *es);
|
||||
static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es);
|
||||
static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es);
|
||||
@ -656,10 +658,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
||||
pname = sname = "Seq Scan";
|
||||
break;
|
||||
case T_IndexScan:
|
||||
if (((IndexScan *) plan)->indexonly)
|
||||
pname = sname = "Index Only Scan";
|
||||
else
|
||||
pname = sname = "Index Scan";
|
||||
pname = sname = "Index Scan";
|
||||
break;
|
||||
case T_IndexOnlyScan:
|
||||
pname = sname = "Index Only Scan";
|
||||
break;
|
||||
case T_BitmapIndexScan:
|
||||
pname = sname = "Bitmap Index Scan";
|
||||
@ -793,42 +795,6 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
||||
|
||||
switch (nodeTag(plan))
|
||||
{
|
||||
case T_IndexScan:
|
||||
{
|
||||
IndexScan *indexscan = (IndexScan *) plan;
|
||||
const char *indexname =
|
||||
explain_get_index_name(indexscan->indexid);
|
||||
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
if (ScanDirectionIsBackward(indexscan->indexorderdir))
|
||||
appendStringInfoString(es->str, " Backward");
|
||||
appendStringInfo(es->str, " using %s", indexname);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *scandir;
|
||||
|
||||
switch (indexscan->indexorderdir)
|
||||
{
|
||||
case BackwardScanDirection:
|
||||
scandir = "Backward";
|
||||
break;
|
||||
case NoMovementScanDirection:
|
||||
scandir = "NoMovement";
|
||||
break;
|
||||
case ForwardScanDirection:
|
||||
scandir = "Forward";
|
||||
break;
|
||||
default:
|
||||
scandir = "???";
|
||||
break;
|
||||
}
|
||||
ExplainPropertyText("Scan Direction", scandir, es);
|
||||
ExplainPropertyText("Index Name", indexname, es);
|
||||
}
|
||||
}
|
||||
/* FALL THRU */
|
||||
case T_SeqScan:
|
||||
case T_BitmapHeapScan:
|
||||
case T_TidScan:
|
||||
@ -840,6 +806,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
||||
case T_ForeignScan:
|
||||
ExplainScanTarget((Scan *) plan, es);
|
||||
break;
|
||||
case T_IndexScan:
|
||||
{
|
||||
IndexScan *indexscan = (IndexScan *) plan;
|
||||
|
||||
ExplainIndexScanDetails(indexscan->indexid,
|
||||
indexscan->indexorderdir,
|
||||
es);
|
||||
ExplainScanTarget((Scan *) indexscan, es);
|
||||
}
|
||||
break;
|
||||
case T_IndexOnlyScan:
|
||||
{
|
||||
IndexOnlyScan *indexonlyscan = (IndexOnlyScan *) plan;
|
||||
|
||||
ExplainIndexScanDetails(indexonlyscan->indexid,
|
||||
indexonlyscan->indexorderdir,
|
||||
es);
|
||||
ExplainScanTarget((Scan *) indexonlyscan, es);
|
||||
}
|
||||
break;
|
||||
case T_BitmapIndexScan:
|
||||
{
|
||||
BitmapIndexScan *bitmapindexscan = (BitmapIndexScan *) plan;
|
||||
@ -1014,6 +1000,19 @@ ExplainNode(PlanState *planstate, List *ancestors,
|
||||
show_instrumentation_count("Rows Removed by Filter", 1,
|
||||
planstate, es);
|
||||
break;
|
||||
case T_IndexOnlyScan:
|
||||
show_scan_qual(((IndexOnlyScan *) plan)->indexqual,
|
||||
"Index Cond", planstate, ancestors, es);
|
||||
if (((IndexOnlyScan *) plan)->indexqual)
|
||||
show_instrumentation_count("Rows Removed by Index Recheck", 2,
|
||||
planstate, es);
|
||||
show_scan_qual(((IndexOnlyScan *) plan)->indexorderby,
|
||||
"Order By", planstate, ancestors, es);
|
||||
show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
|
||||
if (plan->qual)
|
||||
show_instrumentation_count("Rows Removed by Filter", 1,
|
||||
planstate, es);
|
||||
break;
|
||||
case T_BitmapIndexScan:
|
||||
show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
|
||||
"Index Cond", planstate, ancestors, es);
|
||||
@ -1626,6 +1625,45 @@ explain_get_index_name(Oid indexId)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add some additional details about an IndexScan or IndexOnlyScan
|
||||
*/
|
||||
static void
|
||||
ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
|
||||
ExplainState *es)
|
||||
{
|
||||
const char *indexname = explain_get_index_name(indexid);
|
||||
|
||||
if (es->format == EXPLAIN_FORMAT_TEXT)
|
||||
{
|
||||
if (ScanDirectionIsBackward(indexorderdir))
|
||||
appendStringInfoString(es->str, " Backward");
|
||||
appendStringInfo(es->str, " using %s", indexname);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *scandir;
|
||||
|
||||
switch (indexorderdir)
|
||||
{
|
||||
case BackwardScanDirection:
|
||||
scandir = "Backward";
|
||||
break;
|
||||
case NoMovementScanDirection:
|
||||
scandir = "NoMovement";
|
||||
break;
|
||||
case ForwardScanDirection:
|
||||
scandir = "Forward";
|
||||
break;
|
||||
default:
|
||||
scandir = "???";
|
||||
break;
|
||||
}
|
||||
ExplainPropertyText("Scan Direction", scandir, es);
|
||||
ExplainPropertyText("Index Name", indexname, es);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Show the target of a Scan node
|
||||
*/
|
||||
@ -1670,6 +1708,7 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
|
||||
{
|
||||
case T_SeqScan:
|
||||
case T_IndexScan:
|
||||
case T_IndexOnlyScan:
|
||||
case T_BitmapHeapScan:
|
||||
case T_TidScan:
|
||||
case T_ForeignScan:
|
||||
|
Reference in New Issue
Block a user