summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2025-11-27 10:43:28 +1300
committerDavid Rowley <drowley@postgresql.org>2025-11-27 10:43:28 +1300
commit42473b3b31238b15cc3c030b4416b2ee79508d8c (patch)
tree41e1c0dd763abfaa6db3cf9fc1fe7d738dd8164b /src/include
parentdbdc717ac6743074c3a55fc5c380638c91d24afd (diff)
Have the planner replace COUNT(ANY) with COUNT(*), when possible
This adds SupportRequestSimplifyAggref to allow pg_proc.prosupport functions to receive an Aggref and allow them to determine if there is a way that the Aggref call can be optimized. Also added is a support function to allow transformation of COUNT(ANY) into COUNT(*). This is possible to do when the given "ANY" cannot be NULL and also that there are no ORDER BY / DISTINCT clauses within the Aggref. This is a useful transformation to do as it is common that people write COUNT(1), which until now has added unneeded overhead. When counting a NOT NULL column. The overheads can be worse as that might mean deforming more of the tuple, which for large fact tables may be many columns in. It may be possible to add prosupport functions for other aggregates. We could consider if ORDER BY could be dropped for some calls, e.g. the ORDER BY is quite useless in MAX(c ORDER BY c). There is a little bit of passing fallout from adjusting expr_is_nonnullable() to handle Const which results in a plan change in the aggregates.out regression test. Previously, nothing was able to determine that "One-Time Filter: (100 IS NOT NULL)" was always true, therefore useless to include in the plan. Author: David Rowley <dgrowleyml@gmail.com> Reviewed-by: Corey Huinker <corey.huinker@gmail.com> Reviewed-by: Matheus Alcantara <matheusssilv97@gmail.com> Discussion: https://postgr.es/m/CAApHDvqGcPTagXpKfH=CrmHBqALpziThJEDs_MrPqjKVeDF9wA@mail.gmail.com
Diffstat (limited to 'src/include')
-rw-r--r--src/include/nodes/supportnodes.h25
-rw-r--r--src/include/optimizer/optimizer.h3
2 files changed, 28 insertions, 0 deletions
diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h
index ea774c7ef6a..5e89605b76e 100644
--- a/src/include/nodes/supportnodes.h
+++ b/src/include/nodes/supportnodes.h
@@ -72,6 +72,31 @@ typedef struct SupportRequestSimplify
} SupportRequestSimplify;
/*
+ * Similar to SupportRequestSimplify but for Aggref node types.
+ *
+ * This supports conversions such as swapping COUNT(1) or COUNT(notnullcol)
+ * for COUNT(*).
+ *
+ * Supporting functions can consult 'root' and the input 'aggref'. When the
+ * implementing support function deems the simplification is possible, it must
+ * create a new Node (probably another Aggref) and not modify the original.
+ * The newly created Node should then be returned to indicate that the
+ * conversion is to take place. When no conversion is possible, a NULL
+ * pointer should be returned.
+ *
+ * It is important to consider that implementing support functions can receive
+ * Aggrefs with agglevelsup > 0. Careful consideration should be given to
+ * whether the simplification is still possible at levels above 0.
+ */
+typedef struct SupportRequestSimplifyAggref
+{
+ NodeTag type;
+
+ PlannerInfo *root; /* Planner's infrastructure */
+ Aggref *aggref; /* Aggref to be simplified */
+} SupportRequestSimplifyAggref;
+
+/*
* The InlineInFrom request allows the support function to perform plan-time
* simplification of a call to its target function that appears in FROM.
* The rules for this are sufficiently different from ordinary expressions
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index d0aa8ab0c1c..44ec5296a18 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -147,6 +147,9 @@ extern Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
extern bool var_is_nonnullable(PlannerInfo *root, Var *var, bool use_rel_info);
+extern bool expr_is_nonnullable(PlannerInfo *root, Expr *expr,
+ bool use_rel_info);
+
extern List *expand_function_arguments(List *args, bool include_out_arguments,
Oid result_type,
HeapTuple func_tuple);