Skip to content

Commit 8879624

Browse files
committed
Another attempt to resolve contradictory between oid-based and relname-based
approaches to organize ML storage base. In this we store list of oids of persistent tables for each record in the aqo_data table to have a possibility of cleaning records which depends on removed tables. On the other hand, we use relnames (tupDesc hash for TEMP tables) to form a kind of signature of a table. This signature is used for a feature subspace generation.
1 parent de286fe commit 8879624

28 files changed

+967
-376
lines changed

‎Makefile

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# contrib/aqo/Makefile
22

33
EXTENSION = aqo
4-
EXTVERSION = 1.4
4+
EXTVERSION = 1.5
55
PGFILEDESC = "AQO - Adaptive Query Optimization"
66
MODULE_big = aqo
77
OBJS = aqo.o auto_tuning.o cardinality_estimation.o cardinality_hooks.o \
@@ -24,6 +24,7 @@ REGRESS = aqo_disabled \
2424
clean_aqo_data \
2525
plancache \
2626
statement_timeout \
27+
temp_tables \
2728
top_queries
2829

2930
fdw_srcdir = $(top_srcdir)/contrib/postgres_fdw
@@ -33,7 +34,7 @@ EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
3334
EXTRA_INSTALL = contrib/postgres_fdw contrib/pg_stat_statements
3435

3536
DATA = aqo--1.0.sql aqo--1.0--1.1.sql aqo--1.1--1.2.sql aqo--1.2.sql \
36-
aqo--1.2--1.3.sql aqo--1.3--1.4.sql
37+
aqo--1.2--1.3.sql aqo--1.3--1.4.sql aqo--1.4--1.5.sql
3738

3839
ifdef USE_PGXS
3940
PG_CONFIG ?= pg_config

‎aqo--1.4--1.5.sql

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/* contrib/aqo/aqo--1.4--1.5.sql */
2+
3+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
4+
\echo Use "ALTER EXTENSION aqo UPDATE TO '1.5'" to load this file. \quit
5+
6+
--
7+
-- Re-create the aqo_data table. Do so to keep the columns order.
8+
--
9+
DROP TABLE public.aqo_data CASCADE;
10+
CREATE TABLE public.aqo_data (
11+
fspace_hash bigint NOT NULL REFERENCES public.aqo_queries ON DELETE CASCADE,
12+
fsspace_hash int NOT NULL,
13+
nfeatures int NOT NULL,
14+
features double precision[][],
15+
targets double precision[],
16+
oids oid [] DEFAULT NULL,
17+
reliability double precision []
18+
);
19+
CREATE UNIQUE INDEX aqo_fss_access_idx ON public.aqo_data (fspace_hash, fsspace_hash);
20+
21+
22+
--
23+
-- Remove rows from the AQO ML knowledge base, related to previously dropped
24+
-- tables of the database.
25+
--
26+
CREATE OR REPLACE FUNCTION public.clean_aqo_data() RETURNS void AS $$
27+
DECLARE
28+
aqo_data_row aqo_data%ROWTYPE;
29+
aqo_queries_row aqo_queries%ROWTYPE;
30+
aqo_query_texts_row aqo_query_texts%ROWTYPE;
31+
aqo_query_stat_row aqo_query_stat%ROWTYPE;
32+
oid_var oid;
33+
fspace_hash_var bigint;
34+
delete_row boolean DEFAULT false;
35+
BEGIN
36+
FOR aqo_data_row IN (SELECT * FROM aqo_data)
37+
LOOP
38+
delete_row = false;
39+
SELECT aqo_data_row.fspace_hash INTO fspace_hash_var FROM aqo_data;
40+
41+
IF (aqo_data_row.oids IS NOT NULL) THEN
42+
FOREACH oid_var IN ARRAY aqo_data_row.oids
43+
LOOP
44+
IF NOT EXISTS (SELECT relname FROM pg_class WHERE oid = oid_var) THEN
45+
delete_row = true;
46+
END IF;
47+
END LOOP;
48+
END IF;
49+
50+
FOR aqo_queries_row IN (SELECT * FROM public.aqo_queries)
51+
LOOP
52+
IF (delete_row = true AND fspace_hash_var <> 0 AND
53+
fspace_hash_var = aqo_queries_row.fspace_hash AND
54+
aqo_queries_row.fspace_hash = aqo_queries_row.query_hash) THEN
55+
DELETE FROM aqo_data WHERE aqo_data = aqo_data_row;
56+
DELETE FROM aqo_queries WHERE aqo_queries = aqo_queries_row;
57+
58+
FOR aqo_query_texts_row IN (SELECT * FROM aqo_query_texts)
59+
LOOP
60+
DELETE FROM aqo_query_texts
61+
WHERE aqo_query_texts_row.query_hash = fspace_hash_var AND
62+
aqo_query_texts = aqo_query_texts_row;
63+
END LOOP;
64+
65+
FOR aqo_query_stat_row IN (SELECT * FROM aqo_query_stat)
66+
LOOP
67+
DELETE FROM aqo_query_stat
68+
WHERE aqo_query_stat_row.query_hash = fspace_hash_var AND
69+
aqo_query_stat = aqo_query_stat_row;
70+
END LOOP;
71+
END IF;
72+
END LOOP;
73+
END LOOP;
74+
END;
75+
$$ LANGUAGE plpgsql;

‎aqo.control

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# AQO extension
22
comment = 'machine learning for cardinality estimation in optimizer'
3-
default_version = '1.4'
3+
default_version = '1.5'
44
module_pathname = '$libdir/aqo'
55
relocatable = false

‎aqo.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,12 @@ extern bool find_query(uint64 qhash, QueryContextData *ctx);
280280
extern bool update_query(uint64 qhash, uint64 fhash,
281281
bool learn_aqo, bool use_aqo, bool auto_tuning);
282282
extern bool add_query_text(uint64 query_hash, const char *query_string);
283-
extern bool load_fss_ext(uint64 fs, int fss, OkNNrdata *data, List **relnames,
283+
extern bool load_fss_ext(uint64 fs, int fss, OkNNrdata *data, List **reloids,
284284
bool isSafe);
285-
extern bool load_fss(uint64 fs, int fss, OkNNrdata *data, List **relnames);
285+
extern bool load_fss(uint64 fs, int fss, OkNNrdata *data, List **reloids);
286286
extern bool update_fss_ext(uint64 fs, int fss, OkNNrdata *data,
287-
List *relnames, bool isTimedOut);
288-
extern bool update_fss(uint64 fs, int fss, OkNNrdata *data, List *relnames);
287+
List *reloids, bool isTimedOut);
288+
extern bool update_fss(uint64 fs, int fss, OkNNrdata *data, List *reloids);
289289
QueryStat *get_aqo_stat(uint64 query_hash);
290290
void update_aqo_stat(uint64 query_hash, QueryStat * stat);
291291
extern bool my_index_insert(Relation indexRelation, Datum *values, bool *isnull,
@@ -305,8 +305,8 @@ extern void print_into_explain(PlannedStmt *plannedstmt, IntoClause *into,
305305
extern void print_node_explain(ExplainState *es, PlanState *ps, Plan *plan);
306306

307307
/* Cardinality estimation */
308-
double predict_for_relation(List *restrict_clauses, List *selectivities,
309-
List *relnames, int *fss);
308+
extern double predict_for_relation(List *restrict_clauses, List *selectivities,
309+
List *relsigns, int *fss);
310310

311311
/* Query execution statistics collecting hooks */
312312
void aqo_ExecutorStart(QueryDesc *queryDesc, int eflags);

‎cardinality_estimation.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#ifdef AQO_DEBUG_PRINT
2727
static void
2828
predict_debug_output(List *clauses, List *selectivities,
29-
List *relnames, int fss, double result)
29+
List *reloids, int fss, double result)
3030
{
3131
StringInfoData debug_str;
3232
ListCell *lc;
@@ -42,8 +42,8 @@ predict_debug_output(List *clauses, List *selectivities,
4242
appendStringInfo(&debug_str, "%lf ", *s);
4343
}
4444

45-
appendStringInfoString(&debug_str, "}, relnames: { ");
46-
foreach(lc, relnames)
45+
appendStringInfoString(&debug_str, "}, reloids: { ");
46+
foreach(lc, reloids)
4747
{
4848
Value *relname = lfirst_node(String, lc);
4949
appendStringInfo(&debug_str, "%s ", valStr(relname));
@@ -59,22 +59,22 @@ predict_debug_output(List *clauses, List *selectivities,
5959
* General method for prediction the cardinality of given relation.
6060
*/
6161
double
62-
predict_for_relation(List *clauses, List *selectivities,
63-
List *relnames, int *fss)
62+
predict_for_relation(List *clauses, List *selectivities, List *relsigns,
63+
int *fss)
6464
{
6565
double *features;
6666
double result;
6767
int i;
6868
OkNNrdata data;
6969

70-
if (relnames == NIL)
70+
if (relsigns == NIL)
7171
/*
7272
* Don't make prediction for query plans without any underlying plane
7373
* tables. Use return value -4 for debug purposes.
7474
*/
7575
return -4.;
7676

77-
*fss = get_fss_for_object(relnames, clauses, selectivities,
77+
*fss = get_fss_for_object(relsigns, clauses, selectivities,
7878
&data.cols, &features);
7979

8080
if (data.cols > 0)
@@ -94,7 +94,7 @@ predict_for_relation(List *clauses, List *selectivities,
9494
result = -1;
9595
}
9696
#ifdef AQO_DEBUG_PRINT
97-
predict_debug_output(clauses, selectivities, relnames, *fss, result);
97+
predict_debug_output(clauses, selectivities, relsigns, *fss, result);
9898
#endif
9999
pfree(features);
100100
if (data.cols > 0)

‎cardinality_hooks.c

+37-23
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ default_estimate_num_groups(PlannerInfo *root, List *groupExprs,
138138
void
139139
aqo_set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel)
140140
{
141-
double predicted;
142-
RangeTblEntry *rte;
143-
List *relnames = NIL;
144-
List *selectivities = NULL;
145-
List *clauses;
146-
int fss = 0;
141+
double predicted;
142+
RangeTblEntry *rte;
143+
RelSortOut rels = {NIL, NIL};
144+
List *selectivities = NULL;
145+
List *clauses;
146+
int fss = 0;
147147

148148
if (IsQueryDisabled())
149149
/* Fast path. */
@@ -166,16 +166,18 @@ aqo_set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel)
166166
{
167167
/* Predict for a plane table. */
168168
Assert(rte->eref && rte->eref->aliasname);
169-
relnames = list_make1(makeString(pstrdup(rte->eref->aliasname)));
169+
get_list_of_relids(root, rel->relids, &rels);
170170
}
171171

172172
clauses = aqo_get_clauses(root, rel->baserestrictinfo);
173-
predicted = predict_for_relation(clauses, selectivities, relnames, &fss);
173+
predicted = predict_for_relation(clauses, selectivities, rels.signatures,
174+
&fss);
174175
rel->fss_hash = fss;
175176

177+
list_free(rels.hrels);
178+
list_free(rels.signatures);
176179
list_free_deep(selectivities);
177180
list_free(clauses);
178-
list_free(relnames);
179181

180182
if (predicted >= 0)
181183
{
@@ -212,7 +214,7 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
212214
{
213215
double predicted;
214216
RangeTblEntry *rte = NULL;
215-
List *relnames = NIL;
217+
RelSortOut rels = {NIL, NIL};
216218
List *allclauses = NULL;
217219
List *selectivities = NULL;
218220
ListCell *l;
@@ -268,10 +270,12 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
268270
{
269271
/* Predict for a plane table. */
270272
Assert(rte->eref && rte->eref->aliasname);
271-
relnames = list_make1(makeString(pstrdup(rte->eref->aliasname)));
273+
get_list_of_relids(root, rel->relids, &rels);
272274
}
273275

274-
predicted = predict_for_relation(allclauses, selectivities, relnames, &fss);
276+
predicted = predict_for_relation(allclauses, selectivities, rels.signatures, &fss);
277+
list_free(rels.hrels);
278+
list_free(rels.signatures);
275279

276280
predicted_ppi_rows = predicted;
277281
fss_ppi_hash = fss;
@@ -296,7 +300,7 @@ aqo_set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
296300
List *restrictlist)
297301
{
298302
double predicted;
299-
List *relnames;
303+
RelSortOut rels = {NIL, NIL};
300304
List *outer_clauses;
301305
List *inner_clauses;
302306
List *allclauses;
@@ -322,7 +326,7 @@ aqo_set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
322326
goto default_estimator;
323327
}
324328

325-
relnames = get_relnames(root, rel->relids);
329+
get_list_of_relids(root, rel->relids, &rels);
326330
outer_clauses = get_path_clauses(outer_rel->cheapest_total_path, root,
327331
&outer_selectivities);
328332
inner_clauses = get_path_clauses(inner_rel->cheapest_total_path, root,
@@ -333,7 +337,11 @@ aqo_set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
333337
list_concat(outer_selectivities,
334338
inner_selectivities));
335339

336-
predicted = predict_for_relation(allclauses, selectivities, relnames, &fss);
340+
predicted = predict_for_relation(allclauses, selectivities, rels.signatures,
341+
&fss);
342+
list_free(rels.hrels);
343+
list_free(rels.signatures);
344+
337345
rel->fss_hash = fss;
338346

339347
if (predicted >= 0)
@@ -364,7 +372,7 @@ aqo_get_parameterized_joinrel_size(PlannerInfo *root,
364372
List *clauses)
365373
{
366374
double predicted;
367-
List *relnames;
375+
RelSortOut rels = {NIL, NIL};
368376
List *outer_clauses;
369377
List *inner_clauses;
370378
List *allclauses;
@@ -390,7 +398,7 @@ aqo_get_parameterized_joinrel_size(PlannerInfo *root,
390398
goto default_estimator;
391399
}
392400

393-
relnames = get_relnames(root, rel->relids);
401+
get_list_of_relids(root, rel->relids, &rels);
394402
outer_clauses = get_path_clauses(outer_path, root, &outer_selectivities);
395403
inner_clauses = get_path_clauses(inner_path, root, &inner_selectivities);
396404
allclauses = list_concat(aqo_get_clauses(root, clauses),
@@ -399,7 +407,10 @@ aqo_get_parameterized_joinrel_size(PlannerInfo *root,
399407
list_concat(outer_selectivities,
400408
inner_selectivities));
401409

402-
predicted = predict_for_relation(allclauses, selectivities, relnames, &fss);
410+
predicted = predict_for_relation(allclauses, selectivities, rels.signatures,
411+
&fss);
412+
list_free(rels.hrels);
413+
list_free(rels.signatures);
403414

404415
predicted_ppi_rows = predicted;
405416
fss_ppi_hash = fss;
@@ -426,13 +437,16 @@ predict_num_groups(PlannerInfo *root, Path *subpath, List *group_exprs,
426437
child_fss = subpath->parent->fss_hash;
427438
else
428439
{
429-
List *relnames;
430-
List *clauses;
431-
List *selectivities = NIL;
440+
RelSortOut rels = {NIL, NIL};
441+
List *clauses;
442+
List *selectivities = NIL;
432443

433-
relnames = get_relnames(root, subpath->parent->relids);
444+
get_list_of_relids(root, subpath->parent->relids, &rels);
434445
clauses = get_path_clauses(subpath, root, &selectivities);
435-
(void) predict_for_relation(clauses, selectivities, relnames, &child_fss);
446+
(void) predict_for_relation(clauses, selectivities, rels.signatures,
447+
&child_fss);
448+
list_free(rels.hrels);
449+
list_free(rels.signatures);
436450
}
437451

438452
*fss = get_grouped_exprs_hash(child_fss, group_exprs);

0 commit comments

Comments
 (0)