aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/explain.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-10-11 14:20:06 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-10-11 14:21:30 -0400
commita0185461dd94c8d31d8d55a7f2839b0d2f172ab9 (patch)
tree3bd68d4e123336bbdefa8fd92372f0af7fb6d64f /src/backend/commands/explain.c
parentfa351d5a0db0672b6f586315720302e493116f27 (diff)
downloadpostgresql-a0185461dd94c8d31d8d55a7f2839b0d2f172ab9.tar.gz
postgresql-a0185461dd94c8d31d8d55a7f2839b0d2f172ab9.zip
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).
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r--src/backend/commands/explain.c119
1 files changed, 79 insertions, 40 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index fbcaf6cbe09..e38de5c1534 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -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);
@@ -1627,6 +1626,45 @@ explain_get_index_name(Oid indexId)
}
/*
+ * 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
*/
static void
@@ -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: