I wrote:
> There might be some other things we could do to provide a fast-path for
> particularly trivial cases.
I wanted to look into that before the code or tests had drifted far enough
to make comparisons dubious. Attached is a simple patch that lets
grouping_planner fall out with a minimum amount of work if the query is
just "SELECT expression(s)", and a couple of scatter plots of regression
test query timing. The first plot compares pre-pathification timing with
HEAD+this patch, and the second compares HEAD with HEAD+this patch.
I had hoped to see more of a benefit, actually, but it seems like this
might be enough of a win to be worth committing. Probably the main
argument against it is that we'd have to remember to maintain the list
of things-to-check-before-using-the-fast-path.
Thoughts?
regards, tom lane
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5fc8e5b..151f27f 100644
*** a/src/backend/optimizer/plan/planner.c
--- b/src/backend/optimizer/plan/planner.c
*************** grouping_planner(PlannerInfo *root, bool
*** 1458,1463 ****
--- 1458,1504 ----
parse->sortClause,
tlist);
}
+ else if (parse->rtable == NIL &&
+ parse->commandType == CMD_SELECT &&
+ parse->jointree->quals == NULL &&
+ !parse->hasAggs && !parse->hasWindowFuncs &&
+ parse->groupClause == NIL && parse->groupingSets == NIL &&
+ !root->hasHavingQual &&
+ parse->distinctClause == NIL &&
+ parse->sortClause == NIL &&
+ parse->limitOffset == NULL && parse->limitCount == NULL)
+ {
+ /*
+ * Trivial "SELECT expression(s)" query. This case would be handled
+ * correctly by the code below, but it comes up often enough to be
+ * worth having a simplified fast-path for. Need only create a Result
+ * path with the desired targetlist and shove it into the final rel.
+ */
+ Path *path;
+ double tlist_rows;
+
+ /* Need not bother with preprocess_targetlist in a SELECT */
+ root->processed_tlist = tlist;
+
+ final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
+
+ path = (Path *) create_result_path(final_rel,
+ create_pathtarget(root, tlist),
+ NIL);
+
+ /* We do take the trouble to fix the rows estimate for SRFs, though */
+ tlist_rows = tlist_returns_set_rows(tlist);
+ if (tlist_rows > 1)
+ {
+ path->total_cost += path->rows * (tlist_rows - 1) *
+ cpu_tuple_cost / 2;
+ path->rows *= tlist_rows;
+ }
+
+ add_path(final_rel, path);
+
+ return;
+ }
else
{
/* No set operations, do regular planning */