2 36.11. Function Optimization Information #
4 By default, a function is just a “black box” that the database system
5 knows very little about the behavior of. However, that means that
6 queries using the function may be executed much less efficiently than
7 they could be. It is possible to supply additional knowledge that helps
8 the planner optimize function calls.
10 Some basic facts can be supplied by declarative annotations provided in
11 the CREATE FUNCTION command. Most important of these is the function's
12 volatility category (IMMUTABLE, STABLE, or VOLATILE); one should always
13 be careful to specify this correctly when defining a function. The
14 parallel safety property (PARALLEL UNSAFE, PARALLEL RESTRICTED, or
15 PARALLEL SAFE) must also be specified if you hope to use the function
16 in parallelized queries. It can also be useful to specify the
17 function's estimated execution cost, and/or the number of rows a
18 set-returning function is estimated to return. However, the declarative
19 way of specifying those two facts only allows specifying a constant
20 value, which is often inadequate.
22 It is also possible to attach a planner support function to an
23 SQL-callable function (called its target function), and thereby provide
24 knowledge about the target function that is too complex to be
25 represented declaratively. Planner support functions have to be written
26 in C (although their target functions might not be), so this is an
27 advanced feature that relatively few people will use.
29 A planner support function must have the SQL signature
30 supportfn(internal) returns internal
32 It is attached to its target function by specifying the SUPPORT clause
33 when creating the target function.
35 The details of the API for planner support functions can be found in
36 file src/include/nodes/supportnodes.h in the PostgreSQL source code.
37 Here we provide just an overview of what planner support functions can
38 do. The set of possible requests to a support function is extensible,
39 so more things might be possible in future versions.
41 Some function calls can be simplified during planning based on
42 properties specific to the function. For example, int4mul(n, 1) could
43 be simplified to just n. This type of transformation can be performed
44 by a planner support function, by having it implement the
45 SupportRequestSimplify request type. The support function will be
46 called for each instance of its target function found in a query parse
47 tree. If it finds that the particular call can be simplified into some
48 other form, it can build and return a parse tree representing that
49 expression. This will automatically work for operators based on the
50 function, too — in the example just given, n * 1 would also be
51 simplified to n. (But note that this is just an example; this
52 particular optimization is not actually performed by standard
53 PostgreSQL.) We make no guarantee that PostgreSQL will never call the
54 target function in cases that the support function could simplify.
55 Ensure rigorous equivalence between the simplified expression and an
56 actual execution of the target function.
58 For target functions that return boolean, it is often useful to
59 estimate the fraction of rows that will be selected by a WHERE clause
60 using that function. This can be done by a support function that
61 implements the SupportRequestSelectivity request type.
63 If the target function's run time is highly dependent on its inputs, it
64 may be useful to provide a non-constant cost estimate for it. This can
65 be done by a support function that implements the SupportRequestCost
68 For target functions that return sets, it is often useful to provide a
69 non-constant estimate for the number of rows that will be returned.
70 This can be done by a support function that implements the
71 SupportRequestRows request type.
73 For target functions that return boolean, it may be possible to convert
74 a function call appearing in WHERE into an indexable operator clause or
75 clauses. The converted clauses might be exactly equivalent to the
76 function's condition, or they could be somewhat weaker (that is, they
77 might accept some values that the function condition does not). In the
78 latter case the index condition is said to be lossy; it can still be
79 used to scan an index, but the function call will have to be executed
80 for each row returned by the index to see if it really passes the WHERE
81 condition or not. To create such conditions, the support function must
82 implement the SupportRequestIndexCondition request type.