Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit893af51

Browse files
author
Alena Rybakina
committed
Add regression test for checking correct work smart timeout
1 parent442b89d commit893af51

File tree

9 files changed

+152
-60
lines changed

9 files changed

+152
-60
lines changed

‎aqo.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ extern double predict_for_relation(List *restrict_clauses, List *selectivities,
324324
voidaqo_ExecutorStart(QueryDesc*queryDesc,inteflags);
325325
voidaqo_ExecutorRun(QueryDesc*queryDesc,ScanDirectiondirection,
326326
uint64count,boolexecute_once);
327-
voidincrease_flex_timeout(uint64query_hash,int64flex_timeout_fin_time);
327+
voidincrease_flex_timeout(int64flex_timeout_fin_time);
328328
voidaqo_ExecutorEnd(QueryDesc*queryDesc);
329329

330330
/* Automatic query tuning */
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
SET statement_timeout = 5000; -- [0.8s]
2+
DROP TABLE IF EXISTS a,b CASCADE;
3+
NOTICE: table "a" does not exist, skipping
4+
NOTICE: table "b" does not exist, skipping
5+
CREATE TABLE a (x int);
6+
INSERT INTO a (x) SELECT mod(ival,10) FROM generate_series(1,1000) As ival;
7+
CREATE TABLE b (y int);
8+
INSERT INTO b (y) SELECT mod(ival + 1,10) FROM generate_series(1,1000) As ival;
9+
CREATE EXTENSION IF NOT EXISTS aqo;
10+
SET aqo.join_threshold = 0;
11+
SET aqo.mode = 'learn';
12+
SET aqo.show_details = 'off';
13+
SET aqo.learn_statement_timeout = 'on';
14+
SET aqo.statement_timeout = 4; -- [0.8s]
15+
SELECT count(y), pg_sleep(3) FROM a,b where x > 2 * (select min(x) from A,B where x = y);
16+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.000000
17+
count | pg_sleep
18+
--------+----------
19+
900000 |
20+
(1 row)
21+
22+
select * from aqo_queries where query_hash <> 0;
23+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
24+
-------------------+-----------+---------+-------------------+-------------+--------------+------------------------
25+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
26+
(1 row)
27+
28+
SELECT count(y), pg_sleep(3) FROM a,b where x > 3 * (select min(x) from A,B where x = y);
29+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.866297
30+
count | pg_sleep
31+
--------+----------
32+
900000 |
33+
(1 row)
34+
35+
select * from aqo_queries where query_hash <> 0;
36+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
37+
-------------------+-----------+---------+-------------------+-------------+--------------+------------------------
38+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
39+
(1 row)
40+
41+
SELECT count(y), pg_sleep(3) FROM a,b where x > 3 * (select min(x) from A,B where x = y);
42+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.435709
43+
count | pg_sleep
44+
--------+----------
45+
900000 |
46+
(1 row)
47+
48+
select * from aqo_queries where query_hash <> 0;
49+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
50+
-------------------+-----------+---------+-------------------+-------------+--------------+------------------------
51+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
52+
(1 row)
53+
54+
SELECT count(y), pg_sleep(3) FROM a,b where x > (select min(x) from A,B where x = y);
55+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.000000
56+
count | pg_sleep
57+
--------+----------
58+
900000 |
59+
(1 row)
60+
61+
select * from aqo_queries where query_hash <> 0;
62+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
63+
---------------------+-----------+---------+---------------------+-------------+--------------+------------------------
64+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
65+
6582036157989373325 | t | t | 6582036157989373325 | f | 20 | 2
66+
(2 rows)
67+
68+
SELECT count(y), pg_sleep(3) FROM a,b where x > (select min(x) from A,B where x = y);
69+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.866297
70+
count | pg_sleep
71+
--------+----------
72+
900000 |
73+
(1 row)
74+
75+
select * from aqo_queries where query_hash <> 0;
76+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
77+
---------------------+-----------+---------+---------------------+-------------+--------------+------------------------
78+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
79+
6582036157989373325 | t | t | 6582036157989373325 | f | 20 | 2
80+
(2 rows)
81+
82+
SELECT count(y), pg_sleep(3) FROM a,b where x > (select min(x) from A,B where x = y);
83+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.435709
84+
count | pg_sleep
85+
--------+----------
86+
900000 |
87+
(1 row)
88+
89+
select * from aqo_queries where query_hash <> 0;
90+
query_hash | learn_aqo | use_aqo | fspace_hash | auto_tuning | flex_timeout | count_increase_timeout
91+
---------------------+-----------+---------+---------------------+-------------+--------------+------------------------
92+
42929091640608990 | t | t | 42929091640608990 | f | 5 | 1
93+
6582036157989373325 | t | t | 6582036157989373325 | f | 20 | 2
94+
(2 rows)
95+
96+
DROP EXTENSION aqo;

‎expected/statement_timeout.out‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ SET aqo.show_details = 'off';
2727
SET aqo.learn_statement_timeout = 'on';
2828
SET statement_timeout = 800; -- [0.8s]
2929
SELECT *, pg_sleep(1) FROM t;
30-
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data.
30+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 0, mean integral error is 0.000000
3131
ERROR: canceling statement due to statement timeout
3232
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;'); -- haven't any partial data
3333
check_estimated_rows
@@ -38,7 +38,7 @@ SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;'); -- haven't any par
3838
-- Don't learn because running node has smaller cardinality than an optimizer prediction
3939
SET statement_timeout = 3500;
4040
SELECT *, pg_sleep(1) FROM t;
41-
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data.
41+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 0, mean integral error is 0.000000
4242
ERROR: canceling statement due to statement timeout
4343
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
4444
check_estimated_rows
@@ -49,6 +49,7 @@ SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
4949
-- We have a real learning data.
5050
SET statement_timeout = 10000;
5151
SELECT *, pg_sleep(1) FROM t;
52+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 0, mean integral error is 0.000000
5253
x | pg_sleep
5354
---+----------
5455
1 |
@@ -66,12 +67,14 @@ SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
6667

6768
-- Force to make an underestimated prediction
6869
DELETE FROM t WHERE x > 2;
70+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 0.000000
6971
ANALYZE t;
7072
INSERT INTO t (x) (SELECT * FROM generate_series(3,5) AS x);
73+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is -2.697209
7174
TRUNCATE aqo_data;
7275
SET statement_timeout = 800;
7376
SELECT *, pg_sleep(1) FROM t; -- Not learned
74-
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data.
77+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 2.629528
7578
ERROR: canceling statement due to statement timeout
7679
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
7780
check_estimated_rows
@@ -81,16 +84,17 @@ SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
8184

8285
SET statement_timeout = 3500;
8386
SELECT *, pg_sleep(1) FROM t; -- Learn!
84-
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data.
87+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 2.995732
8588
ERROR: canceling statement due to statement timeout
8689
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
8790
check_estimated_rows
8891
----------------------
89-
3
92+
2
9093
(1 row)
9194

9295
SET statement_timeout = 5500;
9396
SELECT *, pg_sleep(1) FROM t; -- Get reliable data
97+
NOTICE: [AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is 4, mean integral error is 2.995732
9498
x | pg_sleep
9599
---+----------
96100
1 |

‎expected/top_queries.out‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,4 @@ ORDER BY (md5(query_text));
9898
SELECT count(*) FROM (SELECT x, y FROM t1 GROUP BY GROUPING SETS ((x,y), (x), (y), ())) AS q1; | 1
9999
(4 rows)
100100

101+
DROP EXTENSION AQO;

‎postprocessing.c‎

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ learnOnPlanState(PlanState *p, void *context)
490490

491491
/*
492492
* It is needed for correct exp(result) calculation.
493-
* Do it before cardinality errorestimation because we can predict no less
493+
* Do it before cardinality errorestmation because we can predict no less
494494
* than 1 tuple, but get zero tuples.
495495
*/
496496
predicted=clamp_row_est(predicted);
@@ -686,6 +686,10 @@ aqo_timeout_handler(void)
686686
{
687687
aqo_obj_statctx= {NIL,NIL,NIL, false, false};
688688

689+
QueryStat*stat=NULL;
690+
doubleerror=0;
691+
int64fintime=0;
692+
689693
if (!timeoutCtl.queryDesc|| !ExtractFromQueryEnv(timeoutCtl.queryDesc))
690694
return;
691695

@@ -694,8 +698,21 @@ aqo_timeout_handler(void)
694698
ctx.learn=query_context.learn_aqo;
695699
ctx.isTimedOut= true;
696700

697-
elog(NOTICE,"[AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Timeout is %d",(int)get_timeout_finish_time(timeoutCtl.id));
698701
learnOnPlanState(timeoutCtl.queryDesc->planstate, (void*)&ctx);
702+
stat=get_aqo_stat(query_context.query_hash);
703+
error=stat->cardinality_error_with_aqo[stat->cardinality_error_with_aqo_size-1]-cardinality_sum_errors/(1+cardinality_num_objects);
704+
fintime= (int64)get_timeout_finish_time(timeoutCtl.id);
705+
706+
elog(NOTICE,"[AQO] Time limit for execution of the statement was expired. AQO tried to learn on partial data. Current timeout is %ld, mean integral error is %f",fintime,error);
707+
708+
if (stat&&aqo_learn_statement_timeout)
709+
{
710+
if (error <=0.1)
711+
{
712+
increase_flex_timeout(fintime);
713+
}
714+
}
715+
699716
}
700717

701718
/*
@@ -714,15 +731,15 @@ get_increment()
714731
*
715732
*/
716733
void
717-
increase_flex_timeout(uint64query_hash,int64flex_timeout_fin_time)
734+
increase_flex_timeout(int64flex_timeout_fin_time)
718735
{
719736
LOCKTAGtag;
720737
flex_timeout_fin_time= (flex_timeout_fin_time+1)*get_increment();
721738

722739
init_lock_tag(&tag,query_context.query_hash,0);
723740
LockAcquire(&tag,ExclusiveLock, false, false);
724-
if (!update_query_timeout(query_hash,flex_timeout_fin_time,query_context.count_increase_timeout+1))
725-
elog(NOTICE,"timeoutis not updated");
741+
if (!update_query_timeout(query_context.query_hash,flex_timeout_fin_time,query_context.count_increase_timeout+1))
742+
elog(NOTICE,"[AQO] Timeoutis not updated!");
726743
LockRelease(&tag,ExclusiveLock, false);
727744
}
728745

@@ -856,25 +873,19 @@ aqo_ExecutorEnd(QueryDesc *queryDesc)
856873
list_free(ctx.selectivities);
857874
}
858875

859-
stat=get_aqo_stat(query_context.query_hash);
860-
if (cardinality_num_objects>0)
861-
cardinality_error=cardinality_sum_errors /cardinality_num_objects;
862-
else
863-
cardinality_error=-1;
864-
865-
if (stat&&aqo_learn_statement_timeout&&
866-
stat->cardinality_error_with_aqo[stat->cardinality_error_with_aqo_size-1]-cardinality_sum_errors/cardinality_num_objects <=0.1)
867-
{
868-
increase_flex_timeout(query_context.query_hash, (int64)get_timeout_finish_time(timeoutCtl.id));
869-
}
870-
871876
if (query_context.collect_stat)
877+
stat=get_aqo_stat(query_context.query_hash);
872878
{
873879
/* Calculate execution time. */
874880
INSTR_TIME_SET_CURRENT(endtime);
875881
INSTR_TIME_SUBTRACT(endtime,query_context.start_execution_time);
876882
execution_time=INSTR_TIME_GET_DOUBLE(endtime);
877883

884+
if (cardinality_num_objects>0)
885+
cardinality_error=cardinality_sum_errors /cardinality_num_objects;
886+
else
887+
cardinality_error=-1;
888+
878889
/* Prevent concurrent updates. */
879890
init_lock_tag(&tag,query_context.query_hash,query_context.fspace_hash);
880891
LockAcquire(&tag,ExclusiveLock, false, false);

‎sql/smart_statement_timeout.sql‎

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
-- The function just copied from stats_ext.sql
2-
createfunctioncheck_estimated_rows(text) returns table (estimatedint, actualint)
3-
language plpgsqlas
4-
$$
5-
declare
6-
lntext;
7-
tmptext[];
8-
first_row bool := true;
9-
begin
10-
for lnin
11-
execute format('explain analyze %s', $1)
12-
loop
13-
if first_row then
14-
first_row := false;
15-
tmp := regexp_match(ln,'rows=(\d*) .* rows=(\d*)');
16-
return queryselect tmp[1]::int, tmp[2]::int;
17-
end if;
18-
end loop;
19-
end;
20-
$$;
21-
221
SET statement_timeout=5000;-- [0.8s]
232

243
DROPTABLE IF EXISTS a,b CASCADE;
@@ -34,10 +13,17 @@ SET aqo.mode = 'learn';
3413
SETaqo.show_details='off';
3514
SETaqo.learn_statement_timeout='on';
3615
SETaqo.statement_timeout=4;-- [0.8s]
37-
SELECT check_estimated_rows('SELECT x FROM A,B where x < 10 and y > 10 group by(x);');-- haven't any partial data
38-
select flex_timeout, count_increase_timeoutfrom aqo_querieswhere query_hash<>0;
39-
SELECT check_estimated_rows('SELECT x FROM A,B where x < 10 and y > 10 group by(x);');-- haven't any partial data
40-
select flex_timeout, count_increase_timeoutfrom aqo_querieswhere query_hash<>0;
41-
SELECT check_estimated_rows('SELECT x FROM A,B where x < 10 and y > 10 group by(x);');-- haven't any partial data
42-
select flex_timeout, count_increase_timeoutfrom aqo_querieswhere query_hash<>0;
43-
SELECT check_estimated_rows('SELECT x FROM A,B where x < 10 and y > 10 group by(x);');-- haven't any partial data
16+
17+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x>2* (selectmin(x)from A,Bwhere x= y);
18+
select*from aqo_querieswhere query_hash<>0;
19+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x>3* (selectmin(x)from A,Bwhere x= y);
20+
select*from aqo_querieswhere query_hash<>0;
21+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x>3* (selectmin(x)from A,Bwhere x= y);
22+
select*from aqo_querieswhere query_hash<>0;
23+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x> (selectmin(x)from A,Bwhere x= y);
24+
select*from aqo_querieswhere query_hash<>0;
25+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x> (selectmin(x)from A,Bwhere x= y);
26+
select*from aqo_querieswhere query_hash<>0;
27+
SELECTcount(y), pg_sleep(3)FROM a,bwhere x> (selectmin(x)from A,Bwhere x= y);
28+
select*from aqo_querieswhere query_hash<>0;
29+
DROP EXTENSION aqo;

‎sql/statement_timeout.sql‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,14 @@ SET aqo.learn_statement_timeout = 'on';
3131
SET statement_timeout=800;-- [0.8s]
3232
SELECT*, pg_sleep(1)FROM t;
3333
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');-- haven't any partial data
34-
3534
-- Don't learn because running node has smaller cardinality than an optimizer prediction
3635
SET statement_timeout=3500;
3736
SELECT*, pg_sleep(1)FROM t;
3837
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
39-
4038
-- We have a real learning data.
4139
SET statement_timeout=10000;
4240
SELECT*, pg_sleep(1)FROM t;
4341
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
44-
4542
-- Force to make an underestimated prediction
4643
DELETEFROM tWHERE x>2;
4744
ANALYZE t;
@@ -51,15 +48,12 @@ TRUNCATE aqo_data;
5148
SET statement_timeout=800;
5249
SELECT*, pg_sleep(1)FROM t;-- Not learned
5350
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
54-
5551
SET statement_timeout=3500;
5652
SELECT*, pg_sleep(1)FROM t;-- Learn!
5753
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
58-
5954
SET statement_timeout=5500;
6055
SELECT*, pg_sleep(1)FROM t;-- Get reliable data
6156
SELECT check_estimated_rows('SELECT *, pg_sleep(1) FROM t;');
62-
6357
DROPTABLE t;
6458
DROP EXTENSION aqo;
6559
DROPFUNCTION check_estimated_rows;

‎sql/top_queries.sql‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ SELECT query_text,nexecs
5050
FROM aqo_cardinality_error(false) ce, aqo_query_texts aqt
5151
WHEREce.id=aqt.query_hash
5252
ORDER BY (md5(query_text));
53+
DROP EXTENSION AQO;

‎storage.c‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,6 @@ update_query_timeout(uint64 qhash, int64 flex_timeout, int64 count_increase_time
238238

239239
index_rescan(scan,&key,1,NULL,0);
240240
slot=MakeSingleTupleTableSlot(hrel->rd_att,&TTSOpsBufferHeapTuple);
241-
values[0]=Int64GetDatum(qhash);
242-
values[5]=Int64GetDatum(flex_timeout);
243-
values[6]=Int64GetDatum(count_increase_timeout);
244241
if (!index_getnext_slot(scan,ForwardScanDirection,slot))
245242
{
246243
result= false;
@@ -254,6 +251,8 @@ update_query_timeout(uint64 qhash, int64 flex_timeout, int64 count_increase_time
254251
*/
255252
tuple=ExecFetchSlotHeapTuple(slot, true,&shouldFree);
256253
Assert(shouldFree!= true);
254+
values[5]=Int64GetDatum(flex_timeout);
255+
values[6]=Int64GetDatum(count_increase_timeout);
257256
nw_tuple=heap_modify_tuple(tuple,hrel->rd_att,values,isnull,replace);
258257

259258
if (my_simple_heap_update(hrel,&(nw_tuple->t_self),nw_tuple,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp