@@ -29,6 +29,7 @@ static bool auto_explain_log_triggers = false;
29
29
static bool auto_explain_log_timing = true;
30
30
static int auto_explain_log_format = EXPLAIN_FORMAT_TEXT ;
31
31
static bool auto_explain_log_nested_statements = false;
32
+ static double auto_explain_sample_ratio = 1 ;
32
33
33
34
static const struct config_enum_entry format_options [] = {
34
35
{"text" , EXPLAIN_FORMAT_TEXT , false},
@@ -47,6 +48,9 @@ static ExecutorRun_hook_type prev_ExecutorRun = NULL;
47
48
static ExecutorFinish_hook_type prev_ExecutorFinish = NULL ;
48
49
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL ;
49
50
51
+ /* Is the current query sampled, per backend */
52
+ static bool current_query_sampled = true;
53
+
50
54
#define auto_explain_enabled () \
51
55
(auto_explain_log_min_duration >= 0 && \
52
56
(nesting_level == 0 || auto_explain_log_nested_statements))
@@ -159,6 +163,19 @@ _PG_init(void)
159
163
NULL ,
160
164
NULL );
161
165
166
+ DefineCustomRealVariable ("auto_explain.sample_ratio" ,
167
+ "Fraction of queries to process." ,
168
+ NULL ,
169
+ & auto_explain_sample_ratio ,
170
+ 1.0 ,
171
+ 0.0 ,
172
+ 1.0 ,
173
+ PGC_SUSET ,
174
+ 0 ,
175
+ NULL ,
176
+ NULL ,
177
+ NULL );
178
+
162
179
EmitWarningsOnPlaceholders ("auto_explain" );
163
180
164
181
/* Install hooks. */
@@ -191,7 +208,15 @@ _PG_fini(void)
191
208
static void
192
209
explain_ExecutorStart (QueryDesc * queryDesc , int eflags )
193
210
{
194
- if (auto_explain_enabled ())
211
+ /*
212
+ * For ratio sampling, randomly choose top-level statement. Either
213
+ * all nested statements will be explained or none will.
214
+ */
215
+ if (auto_explain_log_min_duration >= 0 && nesting_level == 0 )
216
+ current_query_sampled = (random () < auto_explain_sample_ratio *
217
+ MAX_RANDOM_VALUE );
218
+
219
+ if (auto_explain_enabled () && current_query_sampled )
195
220
{
196
221
/* Enable per-node instrumentation iff log_analyze is required. */
197
222
if (auto_explain_log_analyze && (eflags & EXEC_FLAG_EXPLAIN_ONLY ) == 0 )
@@ -210,7 +235,7 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
210
235
else
211
236
standard_ExecutorStart (queryDesc , eflags );
212
237
213
- if (auto_explain_enabled ())
238
+ if (auto_explain_enabled () && current_query_sampled )
214
239
{
215
240
/*
216
241
* Set up to track total elapsed time in ExecutorRun. Make sure the
@@ -280,7 +305,7 @@ explain_ExecutorFinish(QueryDesc *queryDesc)
280
305
static void
281
306
explain_ExecutorEnd (QueryDesc * queryDesc )
282
307
{
283
- if (queryDesc -> totaltime && auto_explain_enabled ())
308
+ if (queryDesc -> totaltime && auto_explain_enabled () && current_query_sampled )
284
309
{
285
310
double msec ;
286
311
0 commit comments