summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/analyze.sgml12
-rw-r--r--src/backend/parser/gram.y28
-rw-r--r--src/backend/tcop/utility.c9
-rw-r--r--src/include/nodes/parsenodes.h6
4 files changed, 50 insertions, 5 deletions
diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml
index 27ab4fca42..f2f3f97e0a 100644
--- a/doc/src/sgml/ref/analyze.sgml
+++ b/doc/src/sgml/ref/analyze.sgml
@@ -22,6 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ] ]
+ANALYZE [ ( { VERBOSE | COORDINATOR } ) ] [ <replaceable class="PARAMETER">table_name</replaceable> [ ( <replaceable class="PARAMETER">column_name</replaceable> [, ...] ) ] ]
</synopsis>
</refsynopsisdiv>
@@ -59,6 +60,17 @@ ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table_name</replaceable> [
</varlistentry>
<varlistentry>
+ <term><literal>COORDINATOR</literal></term>
+ <listitem>
+ <para>
+ Only updates statistics on the coordinator side using current statistics
+on the datanodes. The datanode statistics are not updated and the current
+values are used as they are.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><replaceable class="PARAMETER">table_name</replaceable></term>
<listitem>
<para>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 00744a4980..54af976917 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -308,6 +308,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <ival> opt_lock lock_type cast_context
%type <ival> vacuum_option_list vacuum_option_elem
+%type <ival> analyze_option_list analyze_option_elem
%type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data
@@ -9766,6 +9767,22 @@ AnalyzeStmt:
n->va_cols = $4;
$$ = (Node *)n;
}
+ | analyze_keyword '(' analyze_option_list ')'
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_ANALYZE | $3;
+ n->relation = NULL;
+ n->va_cols = NIL;
+ $$ = (Node *)n;
+ }
+ | analyze_keyword '(' analyze_option_list ')' qualified_name opt_name_list
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_ANALYZE | $3;
+ n->relation = $5;
+ n->va_cols = $6;
+ $$ = (Node *)n;
+ }
;
analyze_keyword:
@@ -9786,6 +9803,17 @@ opt_freeze: FREEZE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
+
+analyze_option_list:
+ analyze_option_elem { $$ = $1; }
+ | analyze_option_list ',' analyze_option_elem { $$ = $1 | $3; }
+ ;
+
+analyze_option_elem:
+ VERBOSE { $$ = VACOPT_VERBOSE; }
+ | COORDINATOR { $$ = VACOPT_COORDINATOR; }
+ ;
+
opt_name_list:
'(' name_list ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 0f42512466..7680a6451a 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -893,14 +893,15 @@ standard_ProcessUtility(Node *parsetree,
/* we choose to allow this during "read only" transactions */
PreventCommandDuringRecovery((stmt->options & VACOPT_VACUUM) ?
"VACUUM" : "ANALYZE");
-#ifdef PGXC
/*
* We have to run the command on nodes before Coordinator because
* vacuum() pops active snapshot and we can not send it to nodes
*/
- if (IS_PGXC_LOCAL_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, true, EXEC_ON_DATANODES, false);
-#endif
+ if (IS_PGXC_LOCAL_COORDINATOR &&
+ !(stmt->options & VACOPT_COORDINATOR))
+ ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
+ true,
+ EXEC_ON_DATANODES, false);
/* forbidden in parallel mode due to CommandIsReadOnly */
ExecVacuum(stmt, isTopLevel);
}
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 751f67285a..8c78e3eb2b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2855,7 +2855,11 @@ typedef enum VacuumOption
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
VACOPT_NOWAIT = 1 << 5, /* don't wait to get lock (autovacuum only) */
VACOPT_SKIPTOAST = 1 << 6, /* don't process the TOAST table, if any */
- VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */
+ VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7, /* don't skip any pages */
+ VACOPT_COORDINATOR = 1 << 8 /* don't trigger analyze on the datanodes, but
+ * just collect existing info and populate
+ * coordinator side stats.
+ */
} VacuumOption;
typedef struct VacuumStmt