diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-10-11 14:20:06 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-10-11 14:21:30 -0400 |
commit | a0185461dd94c8d31d8d55a7f2839b0d2f172ab9 (patch) | |
tree | 3bd68d4e123336bbdefa8fd92372f0af7fb6d64f /src/backend/commands/explain.c | |
parent | fa351d5a0db0672b6f586315720302e493116f27 (diff) | |
download | postgresql-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.c | 119 |
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: |