Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit939f0fb

Browse files
committed
Improve performance of EXPLAIN with large range tables.
As of 9.3, ruleutils.c goes to some lengths to ensure that table and columnaliases used in its output are unique. Of course this takes more time thanwas required before, which in itself isn't fatal. However, EXPLAIN was setup so that recalculation of the unique aliases was repeated for eachsubexpression printed in a plan. That results in O(N^2) time and memoryconsumption for large plan trees, which did not happen in older branches.Fortunately, the expensive work is the same across a whole plan tree,so there is no need to repeat it; we can do most of the initializationjust once per query and re-use it for each subexpression. This buysback most (not all) of the performance loss since 9.2.We need an extra ExplainState field to hold the precalculated deparsecontext. That's no problem in HEAD, but in the back branches, expandingsizeof(ExplainState) seems risky because third-party extensions mighthave local variables of that struct type. So, in 9.4 and 9.3, introducean auxiliary struct to keep sizeof(ExplainState) the same. We shouldrefactor the APIs to avoid such local variables in future, but that'smaterial for a separate HEAD-only commit.Per gripe from Alexey Bashtanov. Back-patch to 9.3 where the issuewas introduced.
1 parentebbef4f commit939f0fb

File tree

4 files changed

+77
-37
lines changed

4 files changed

+77
-37
lines changed

‎src/backend/commands/explain.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#include"utils/xml.h"
3434

3535

36+
/* Crude hack to avoid changing sizeof(ExplainState) in released branches */
37+
#definegrouping_stack extra->groupingstack
38+
#definedeparse_cxt extra->deparsecxt
39+
3640
/* Hook for plugins to get control in ExplainOneQuery() */
3741
ExplainOneQuery_hook_typeExplainOneQuery_hook=NULL;
3842

@@ -253,6 +257,8 @@ ExplainInitState(ExplainState *es)
253257
es->costs= true;
254258
/* Prepare output buffer. */
255259
es->str=makeStringInfo();
260+
/* Kluge to avoid changing sizeof(ExplainState) in released branches. */
261+
es->extra= (ExplainStateExtra*)palloc0(sizeof(ExplainStateExtra));
256262
}
257263

258264
/*
@@ -555,6 +561,8 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
555561
es->rtable=queryDesc->plannedstmt->rtable;
556562
ExplainPreScanNode(queryDesc->planstate,&rels_used);
557563
es->rtable_names=select_rtable_names_for_explain(es->rtable,rels_used);
564+
es->deparse_cxt=deparse_context_for_plan_rtable(es->rtable,
565+
es->rtable_names);
558566
ExplainNode(queryDesc->planstate,NIL,NULL,NULL,es);
559567
}
560568

@@ -1585,10 +1593,9 @@ show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es)
15851593
return;
15861594

15871595
/* Set up deparsing context */
1588-
context=deparse_context_for_planstate((Node*)planstate,
1589-
ancestors,
1590-
es->rtable,
1591-
es->rtable_names);
1596+
context=set_deparse_context_planstate(es->deparse_cxt,
1597+
(Node*)planstate,
1598+
ancestors);
15921599
useprefix=list_length(es->rtable)>1;
15931600

15941601
/* Deparse each result column (we now include resjunk ones) */
@@ -1617,10 +1624,9 @@ show_expression(Node *node, const char *qlabel,
16171624
char*exprstr;
16181625

16191626
/* Set up deparsing context */
1620-
context=deparse_context_for_planstate((Node*)planstate,
1621-
ancestors,
1622-
es->rtable,
1623-
es->rtable_names);
1627+
context=set_deparse_context_planstate(es->deparse_cxt,
1628+
(Node*)planstate,
1629+
ancestors);
16241630

16251631
/* Deparse the expression */
16261632
exprstr=deparse_expression(node,context,useprefix, false);
@@ -1720,10 +1726,9 @@ show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols,
17201726
return;
17211727

17221728
/* Set up deparsing context */
1723-
context=deparse_context_for_planstate((Node*)planstate,
1724-
ancestors,
1725-
es->rtable,
1726-
es->rtable_names);
1729+
context=set_deparse_context_planstate(es->deparse_cxt,
1730+
(Node*)planstate,
1731+
ancestors);
17271732
useprefix= (list_length(es->rtable)>1||es->verbose);
17281733

17291734
for (keyno=0;keyno<nkeys;keyno++)

‎src/backend/utils/adt/ruleutils.c

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2370,7 +2370,43 @@ deparse_context_for(const char *aliasname, Oid relid)
23702370
}
23712371

23722372
/*
2373-
* deparse_context_for_planstate- Build deparse context for a plan
2373+
* deparse_context_for_plan_rtable - Build deparse context for a plan's rtable
2374+
*
2375+
* When deparsing an expression in a Plan tree, we use the plan's rangetable
2376+
* to resolve names of simple Vars. The initialization of column names for
2377+
* this is rather expensive if the rangetable is large, and it'll be the same
2378+
* for every expression in the Plan tree; so we do it just once and re-use
2379+
* the result of this function for each expression. (Note that the result
2380+
* is not usable until set_deparse_context_planstate() is applied to it.)
2381+
*
2382+
* In addition to the plan's rangetable list, pass the per-RTE alias names
2383+
* assigned by a previous call to select_rtable_names_for_explain.
2384+
*/
2385+
List*
2386+
deparse_context_for_plan_rtable(List*rtable,List*rtable_names)
2387+
{
2388+
deparse_namespace*dpns;
2389+
2390+
dpns= (deparse_namespace*)palloc0(sizeof(deparse_namespace));
2391+
2392+
/* Initialize fields that stay the same across the whole plan tree */
2393+
dpns->rtable=rtable;
2394+
dpns->rtable_names=rtable_names;
2395+
dpns->ctes=NIL;
2396+
2397+
/*
2398+
* Set up column name aliases. We will get rather bogus results for join
2399+
* RTEs, but that doesn't matter because plan trees don't contain any join
2400+
* alias Vars.
2401+
*/
2402+
set_simple_column_names(dpns);
2403+
2404+
/* Return a one-deep namespace stack */
2405+
returnlist_make1(dpns);
2406+
}
2407+
2408+
/*
2409+
* set_deparse_context_planstate- Specify Plan node containing expression
23742410
*
23752411
* When deparsing an expression in a Plan tree, we might have to resolve
23762412
* OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must
@@ -2389,37 +2425,28 @@ deparse_context_for(const char *aliasname, Oid relid)
23892425
* most-closely-nested first. This is needed to resolve PARAM_EXEC Params.
23902426
* Note we assume that all the PlanStates share the same rtable.
23912427
*
2392-
* The plan's rangetable list must also be passed, along with the per-RTE
2393-
* alias names assigned by a previous call to select_rtable_names_for_explain.
2394-
* (We use the rangetable to resolve simple Vars, but the plan inputs are
2395-
* necessary for Vars with special varnos.)
2428+
* Once this function has been called, deparse_expression() can be called on
2429+
* subsidiary expression(s) of the specified PlanState node. To deparse
2430+
* expressions of a different Plan node in the same Plan tree, re-call this
2431+
* function to identify the new parent Plan node.
2432+
*
2433+
* The result is the same List passed in; this is a notational convenience.
23962434
*/
23972435
List*
2398-
deparse_context_for_planstate(Node*planstate,List*ancestors,
2399-
List*rtable,List*rtable_names)
2436+
set_deparse_context_planstate(List*dpcontext,
2437+
Node*planstate,List*ancestors)
24002438
{
24012439
deparse_namespace*dpns;
24022440

2403-
dpns= (deparse_namespace*)palloc0(sizeof(deparse_namespace));
2404-
2405-
/* Initialize fields that stay the same across the whole plan tree */
2406-
dpns->rtable=rtable;
2407-
dpns->rtable_names=rtable_names;
2408-
dpns->ctes=NIL;
2409-
2410-
/*
2411-
* Set up column name aliases. We will get rather bogus results for join
2412-
* RTEs, but that doesn't matter because plan trees don't contain any join
2413-
* alias Vars.
2414-
*/
2415-
set_simple_column_names(dpns);
2441+
/* Should always have one-entry namespace list for Plan deparsing */
2442+
Assert(list_length(dpcontext)==1);
2443+
dpns= (deparse_namespace*)linitial(dpcontext);
24162444

24172445
/* Set our attention on the specific plan node passed in */
24182446
set_deparse_planstate(dpns, (PlanState*)planstate);
24192447
dpns->ancestors=ancestors;
24202448

2421-
/* Return a one-deep namespace stack */
2422-
returnlist_make1(dpns);
2449+
returndpcontext;
24232450
}
24242451

24252452
/*

‎src/include/commands/explain.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ typedef enum ExplainFormat
2424
EXPLAIN_FORMAT_YAML
2525
}ExplainFormat;
2626

27+
/* Crude hack to avoid changing sizeof(ExplainState) in released branches */
28+
typedefstructExplainStateExtra
29+
{
30+
List*groupingstack;/* format-specific grouping state */
31+
List*deparsecxt;/* context list for deparsing expressions */
32+
}ExplainStateExtra;
33+
2734
typedefstructExplainState
2835
{
2936
StringInfostr;/* output buffer */
@@ -39,7 +46,7 @@ typedef struct ExplainState
3946
List*rtable;/* range table */
4047
List*rtable_names;/* alias names for RTEs */
4148
intindent;/* current indentation level */
42-
List*grouping_stack;/*format-specific grouping state */
49+
ExplainStateExtra*extra;/*pointer to additional data */
4350
}ExplainState;
4451

4552
/* Hook for plugins to get control in ExplainOneQuery() */

‎src/include/utils/builtins.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,9 @@ extern Datum pg_get_function_result(PG_FUNCTION_ARGS);
660660
externchar*deparse_expression(Node*expr,List*dpcontext,
661661
boolforceprefix,boolshowimplicit);
662662
externList*deparse_context_for(constchar*aliasname,Oidrelid);
663-
externList*deparse_context_for_planstate(Node*planstate,List*ancestors,
664-
List*rtable,List*rtable_names);
663+
externList*deparse_context_for_plan_rtable(List*rtable,List*rtable_names);
664+
externList*set_deparse_context_planstate(List*dpcontext,
665+
Node*planstate,List*ancestors);
665666
externList*select_rtable_names_for_explain(List*rtable,
666667
Bitmapset*rels_used);
667668
externconstchar*quote_identifier(constchar*ident);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp