Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3e25d79

Browse files
author
Oleg Ivanov
committed
Added protection from infinite cardinality convergence
1 parent a5f76ed commit 3e25d79

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

contrib/aqo/aqo.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ static const struct config_enum_entry format_options[] = {
1717
};
1818

1919
/* Parameters of autotuning */
20-
int aqo_stat_size = 10;
20+
int aqo_stat_size = 20;
2121
int auto_tuning_window_size = 5;
2222
double auto_tuning_exploration = 0.1;
2323
int auto_tuning_max_iterations = 50;
24+
int auto_tuning_infinite_loop = 8;
25+
26+
/* stat_size > infinite_loop + window_size + 3 is required for auto_tuning*/
2427

2528
/* Machine learning parameters */
2629
double object_selection_prediction_threshold = 0.3;

contrib/aqo/aqo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* "intelligent" mode tries to automatically tune AQO settings for the current
3131
* workload. It creates separate feature space for each new type of query
3232
* and then tries to improve the performance of such query type execution.
33-
* The automatic tuning may be manually deactivated for the given queries.
33+
* The automatic tuning may be manually deactivated for some queries.
3434
* "forced" mode makes no difference between query types and use AQO for them
3535
* all in the similar way. It considers each new query type as linked to special
3636
* feature space called COMMON with hash 0.
@@ -174,6 +174,7 @@ extern int aqo_stat_size;
174174
extern int auto_tuning_window_size;
175175
extern double auto_tuning_exploration;
176176
extern int auto_tuning_max_iterations;
177+
extern int auto_tuning_infinite_loop;
177178

178179
/* Machine learning parameters */
179180
extern double object_selection_prediction_threshold;

contrib/aqo/auto_tuning.c

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,55 @@
99
*
1010
*****************************************************************************/
1111

12+
static double get_mean(double *elems, int nelems);
1213
static double get_estimation(double *elems, int nelems);
14+
static bool is_stable(double *elems, int nelems);
1315
static bool converged_cq(double *elems, int nelems);
16+
static bool is_in_infinite_loop_cq(double *elems, int nelems);
1417

1518

19+
/*
20+
* Returns mean value of the array of doubles.
21+
*/
22+
double
23+
get_mean(double *elems, int nelems)
24+
{
25+
double sum = 0;
26+
int i;
27+
28+
for (i = 0; i < nelems; ++i)
29+
sum += elems[i];
30+
return sum / nelems;
31+
}
32+
1633
/*
1734
* Having a time series it tries to predict its next value.
1835
* Now it do simple window averaging.
1936
*/
2037
double
2138
get_estimation(double *elems, int nelems)
2239
{
23-
double sum = 0;
24-
int i;
40+
int start;
41+
42+
if (nelems > auto_tuning_window_size)
43+
start = nelems - auto_tuning_window_size;
44+
else
45+
start = 0;
2546

26-
for (i = 0; i < auto_tuning_window_size; ++i)
27-
sum += elems[nelems - 1 - i];
28-
return sum / auto_tuning_window_size;
47+
return get_mean(&elems[start], nelems - start);
48+
}
49+
50+
/*
51+
* Checks whether the series is stable with absolute or relative error 0.1.
52+
*/
53+
bool
54+
is_stable(double *elems, int nelems)
55+
{
56+
double est;
57+
58+
est = get_mean(elems, nelems - 1);
59+
return (est * 1.1 > elems[nelems - 1] || est + 0.1 > elems[nelems - 1]) &&
60+
(est * 0.9 < elems[nelems - 1] || est - 0.1 < elems[nelems - 1]);
2961
}
3062

3163
/*
@@ -37,14 +69,27 @@ get_estimation(double *elems, int nelems)
3769
bool
3870
converged_cq(double *elems, int nelems)
3971
{
40-
double est;
41-
4272
if (nelems < auto_tuning_window_size + 2)
4373
return false;
4474

45-
est = get_estimation(elems, nelems - 1);
46-
return (est * 1.1 > elems[nelems - 1] || est + 0.1 > elems[nelems - 1]) &&
47-
(est * 0.9 < elems[nelems - 1] || est - 0.1 < elems[nelems - 1]);
75+
return is_stable(&elems[nelems - auto_tuning_window_size - 1],
76+
auto_tuning_window_size + 1);
77+
}
78+
79+
/*
80+
* Tests whether cardinality qualities series is converged, i. e. learning
81+
* process may be considered as finished.
82+
* Now it checks whether the cardinality quality stopped decreasing with
83+
* absolute or relative error 0.1.
84+
*/
85+
bool
86+
is_in_infinite_loop_cq(double *elems, int nelems)
87+
{
88+
if (nelems - auto_tuning_infinite_loop > auto_tuning_window_size + 2)
89+
return false;
90+
91+
return !converged_cq(elems, nelems) &&
92+
!converged_cq(elems, nelems - auto_tuning_window_size);
4893
}
4994

5095
/*
@@ -69,7 +114,7 @@ converged_cq(double *elems, int nelems)
69114
* If we find out that cardinality quality diverged during the exploration, we
70115
* return to step 2 and run the query type with both AQO usage and AQO learning
71116
* enabled until convergence.
72-
* If after auto_tuning_max_iterations steps we consider that for this query
117+
* If after auto_tuning_max_iterations steps we see that for this query
73118
* it is better not to use AQO, we set auto_tuning, learn_aqo and use_aqo for
74119
* this query to false.
75120
*/
@@ -87,7 +132,9 @@ automatical_query_tuning(int query_hash, QueryStat * stat)
87132
if (stat->executions_without_aqo < auto_tuning_window_size + 1)
88133
use_aqo = false;
89134
else if (!converged_cq(stat->cardinality_error_with_aqo,
90-
stat->cardinality_error_with_aqo_size))
135+
stat->cardinality_error_with_aqo_size) &&
136+
!is_in_infinite_loop_cq(stat->cardinality_error_with_aqo,
137+
stat->cardinality_error_with_aqo_size))
91138
use_aqo = true;
92139
else
93140
{

0 commit comments

Comments
 (0)