9
9
*
10
10
*****************************************************************************/
11
11
12
+ static double get_mean (double * elems , int nelems );
12
13
static double get_estimation (double * elems , int nelems );
14
+ static bool is_stable (double * elems , int nelems );
13
15
static bool converged_cq (double * elems , int nelems );
16
+ static bool is_in_infinite_loop_cq (double * elems , int nelems );
14
17
15
18
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
+
16
33
/*
17
34
* Having a time series it tries to predict its next value.
18
35
* Now it do simple window averaging.
19
36
*/
20
37
double
21
38
get_estimation (double * elems , int nelems )
22
39
{
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 ;
25
46
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 ]);
29
61
}
30
62
31
63
/*
@@ -37,14 +69,27 @@ get_estimation(double *elems, int nelems)
37
69
bool
38
70
converged_cq (double * elems , int nelems )
39
71
{
40
- double est ;
41
-
42
72
if (nelems < auto_tuning_window_size + 2 )
43
73
return false;
44
74
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 );
48
93
}
49
94
50
95
/*
@@ -69,7 +114,7 @@ converged_cq(double *elems, int nelems)
69
114
* If we find out that cardinality quality diverged during the exploration, we
70
115
* return to step 2 and run the query type with both AQO usage and AQO learning
71
116
* 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
73
118
* it is better not to use AQO, we set auto_tuning, learn_aqo and use_aqo for
74
119
* this query to false.
75
120
*/
@@ -87,7 +132,9 @@ automatical_query_tuning(int query_hash, QueryStat * stat)
87
132
if (stat -> executions_without_aqo < auto_tuning_window_size + 1 )
88
133
use_aqo = false;
89
134
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 ))
91
138
use_aqo = true;
92
139
else
93
140
{
0 commit comments