Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 09cd836

Browse files
author
Artem Fadeev
committedSep 30, 2024·
Fix build_knn_matrix (now called update_knn_matrix)
Previous version of build_knn_matrix had an unreachable branch (`if (features!=NULL)`), which lead to use_wide_search having no effect. There was also a memory bug of copying a memory area into itself. predict_for_relation was fixed with interoperation of use_wide_search and predict_with_few_neighbors features in mind. Additions to the look_a_like regression test reflect those changes. This commit also removes unused arguments from several functions and fixes a couple of typos.
1 parent 7ff9d8b commit 09cd836

11 files changed

+248
-77
lines changed
 

‎cardinality_estimation.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,17 @@ predict_for_relation(List *clauses, List *selectivities, List *relsigns,
8181
&ncols, &features);
8282
data = OkNNr_allocate(ncols);
8383

84-
if (load_fss_ext(query_context.fspace_hash, *fss, data, NULL))
84+
if (load_aqo_data(query_context.fspace_hash, *fss, data, false) &&
85+
data->rows >= (aqo_predict_with_few_neighbors ? 1 : aqo_k))
8586
result = OkNNr_predict(data, features);
87+
/* Try to search in surrounding feature spaces for the same node */
88+
else if (use_wide_search && load_aqo_data(query_context.fspace_hash, *fss, data, true))
89+
{
90+
elog(DEBUG5, "[AQO] Make prediction for fss "INT64_FORMAT" by a neighbour "
91+
"includes %d feature(s) and %d fact(s).",
92+
(int64) *fss, data->cols, data->rows);
93+
result = OkNNr_predict(data, features);
94+
}
8695
else
8796
{
8897
/*
@@ -91,17 +100,7 @@ predict_for_relation(List *clauses, List *selectivities, List *relsigns,
91100
* small part of paths was used for AQO learning and stored into
92101
* the AQO knowledge base.
93102
*/
94-
95-
/* Try to search in surrounding feature spaces for the same node */
96-
if (!load_aqo_data(query_context.fspace_hash, *fss, data, NULL, use_wide_search, features))
97-
result = -1;
98-
else
99-
{
100-
elog(DEBUG5, "[AQO] Make prediction for fss %d by a neighbour "
101-
"includes %d feature(s) and %d fact(s).",
102-
*fss, data->cols, data->rows);
103-
result = OkNNr_predict(data, features);
104-
}
103+
result = -1;
105104
}
106105

107106
#ifdef AQO_DEBUG_PRINT

‎cardinality_hooks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ predict_num_groups(PlannerInfo *root, Path *subpath, List *group_exprs,
414414
*fss = get_grouped_exprs_hash(child_fss, group_exprs);
415415
memset(&data, 0, sizeof(OkNNrdata));
416416

417-
if (!load_fss_ext(query_context.fspace_hash, *fss, &data, NULL))
417+
if (!load_aqo_data(query_context.fspace_hash, *fss, &data, false))
418418
return -1;
419419

420420
Assert(data.rows == 1);

‎expected/gucs.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,5 @@ SELECT count(*) FROM aqo_query_stat;
145145
0
146146
(1 row)
147147

148+
DROP TABLE t;
148149
DROP EXTENSION aqo;

‎expected/look_a_like.out

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ SELECT true AS success FROM aqo_reset();
99
SET aqo.wide_search = 'on';
1010
SET aqo.mode = 'learn';
1111
SET aqo.show_details = 'on';
12-
set aqo.show_hash = 'off';
12+
SET aqo.show_hash = 'off';
1313
SET aqo.min_neighbors_for_predicting = 1;
14+
SET aqo.predict_with_few_neighbors = 'off';
1415
SET enable_nestloop = 'off';
1516
SET enable_mergejoin = 'off';
1617
SET enable_material = 'off';
@@ -553,9 +554,131 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L
553554
JOINS: 2
554555
(24 rows)
555556

557+
-- Next few test cases focus on fss corresponding to (x1 > ? AND x2 < ? AND x3 < ?). We will denote
558+
-- it by fss0. At this moment there is exactly one fs with (fs, fss0, dbid) record in aqo_data. We'll
559+
-- refer to it as fs0.
560+
-- Let's create another fs for fss0. We'll call this fs fs1. Since aqo.wide_search='on',
561+
-- aqo.min_neighbors_for_predicting=1, and there is (fs0, fss0, dbid) data record, AQO must be used here.
562+
SELECT str AS result
563+
FROM expln('
564+
SELECT * FROM A WHERE x1 > -100 AND x2 < 10 AND x3 < 10;') AS str
565+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
566+
result
567+
----------------------------------------------------------------------
568+
Seq Scan on public.a (actual rows=100 loops=1)
569+
AQO: rows=20, error=-400%
570+
Output: x1, x2, x3
571+
Filter: ((a.x1 > '-100'::integer) AND (a.x2 < 10) AND (a.x3 < 10))
572+
Using aqo: true
573+
AQO mode: LEARN
574+
JOINS: 0
575+
(7 rows)
576+
577+
-- Now there are 2 data records for fss0: one for (fs0, fss0, dbid) and one for (fs1, fss0, dbid)
578+
-- We repeat previous query, but set aqo.min_neighbors_for_predicting to 2. Since aqo.predict_with_few_neighbors
579+
-- is 'off', AQO is obliged to use both data records for fss0.
580+
SET aqo.min_neighbors_for_predicting = 2;
581+
SELECT str AS result
582+
FROM expln('
583+
SELECT * FROM A WHERE x1 > 1 AND x2 < 10 AND x3 < 10;') AS str
584+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
585+
result
586+
--------------------------------------------------------
587+
Seq Scan on public.a (actual rows=80 loops=1)
588+
AQO: rows=77, error=-4%
589+
Output: x1, x2, x3
590+
Filter: ((a.x1 > 1) AND (a.x2 < 10) AND (a.x3 < 10))
591+
Rows Removed by Filter: 20
592+
Using aqo: true
593+
AQO mode: LEARN
594+
JOINS: 0
595+
(8 rows)
596+
597+
-- Now there are 3 data records for fss0: 1 for (fs0, fss0, dbid) and 2 for (fs1, fss0, dbid)
598+
-- Lastly, we run invoke query with previously unseen fs with fss0 feature subspace. AQO must use
599+
-- three data records from two neighbors for this one.
600+
SET aqo.min_neighbors_for_predicting = 3;
601+
SELECT str AS result
602+
FROM expln('
603+
SELECT x2 FROM A WHERE x1 > 3 AND x2 < 10 AND x3 < 10 GROUP BY(x2);') AS str
604+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
605+
result
606+
--------------------------------------------------------------
607+
HashAggregate (actual rows=6 loops=1)
608+
AQO not used
609+
Output: x2
610+
Group Key: a.x2
611+
-> Seq Scan on public.a (actual rows=60 loops=1)
612+
AQO: rows=71, error=15%
613+
Output: x1, x2, x3
614+
Filter: ((a.x1 > 3) AND (a.x2 < 10) AND (a.x3 < 10))
615+
Rows Removed by Filter: 40
616+
Using aqo: true
617+
AQO mode: LEARN
618+
JOINS: 0
619+
(12 rows)
620+
621+
-----
622+
DROP TABLE IF EXISTS t;
623+
NOTICE: table "t" does not exist, skipping
624+
CREATE TABLE t AS SELECT x, x AS y, x AS z FROM generate_series(1, 10000) x;
625+
ANALYZE t;
626+
SELECT true AS success FROM aqo_reset();
627+
success
628+
---------
629+
t
630+
(1 row)
631+
632+
-- Test that when there are less records than aqo.min_neighbors_for_predicting for given (fs, fss, dbid)
633+
-- and aqo.predict_with_few_neighbors is off, those records have higher precedence for cardinality estimation
634+
-- than neighbors' records.
635+
SELECT str AS result
636+
FROM expln('
637+
select * from t where x <= 10000 and y <= 10000 and z <= 10000;') AS str
638+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
639+
result
640+
------------------------------------------------------------------
641+
Seq Scan on public.t (actual rows=10000 loops=1)
642+
AQO not used
643+
Output: x, y, z
644+
Filter: ((t.x <= 10000) AND (t.y <= 10000) AND (t.z <= 10000))
645+
Using aqo: true
646+
AQO mode: LEARN
647+
JOINS: 0
648+
(7 rows)
649+
650+
DO
651+
$$
652+
BEGIN
653+
for counter in 1..20 loop
654+
EXECUTE format('explain analyze select *, 1 from t where x <= 1 and y <= 1 and z <= %L;', 10 * counter);
655+
EXECUTE format('explain analyze select *, 1 from t where x <= 1 and y <= %L and z <= 1;', 10 * counter);
656+
EXECUTE format('explain analyze select *, 1 from t where x <= %L and y <= 1 and z <= 1;', 10 * counter);
657+
end loop;
658+
END;
659+
$$ LANGUAGE PLPGSQL;
660+
-- AQO should predict ~1000 rows to indicate that the record from previous invocation was used.
661+
SELECT str AS result
662+
FROM expln('
663+
select * from t where x <= 10000 and y <= 10000 and z <= 10000;') AS str
664+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
665+
result
666+
------------------------------------------------------------------
667+
Seq Scan on public.t (actual rows=10000 loops=1)
668+
AQO: rows=9987, error=-0%
669+
Output: x, y, z
670+
Filter: ((t.x <= 10000) AND (t.y <= 10000) AND (t.z <= 10000))
671+
Using aqo: true
672+
AQO mode: LEARN
673+
JOINS: 0
674+
(7 rows)
675+
556676
RESET aqo.wide_search;
677+
RESET aqo.predict_with_few_neighbors;
678+
RESET aqo.min_neighbors_for_predicting;
557679
DROP EXTENSION aqo CASCADE;
558680
DROP TABLE a;
559681
DROP TABLE b;
560682
DROP TABLE c;
683+
DROP TABLE t;
561684
DROP FUNCTION expln;

‎expected/unsupported.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ $$ LANGUAGE PLPGSQL;
1616
SET aqo.mode = 'learn';
1717
SET aqo.show_details = 'on';
1818
DROP TABLE IF EXISTS t;
19+
NOTICE: table "t" does not exist, skipping
1920
CREATE TABLE t AS SELECT (gs.* / 50) AS x FROM generate_series(1,1000) AS gs;
2021
ANALYZE t;
2122
CREATE TABLE t1 AS SELECT mod(gs,10) AS x, mod(gs+1,10) AS y

‎machine_learning.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ OkNNr_predict(OkNNrdata *data, double *features)
150150

151151
if (!aqo_predict_with_few_neighbors && data->rows < aqo_k)
152152
return -1.;
153+
Assert(data->rows > 0);
153154

154155
for (i = 0; i < data->rows; ++i)
155156
distances[i] = fs_distance(data->matrix[i], features, data->cols);

‎postprocessing.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ atomic_fss_learn_step(uint64 fs, int fss, OkNNrdata *data,
9696
double *features, double target, double rfactor,
9797
List *reloids)
9898
{
99-
if (!load_fss_ext(fs, fss, data, NULL))
99+
if (!load_aqo_data(fs, fss, data, false))
100100
data->rows = 0;
101101

102102
data->rows = OkNNr_learn(data, features, target, rfactor);

‎sql/gucs.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ SELECT count(*) FROM aqo_query_stat;
5151
SELECT true AS success FROM aqo_reset();
5252
SELECT count(*) FROM aqo_query_stat;
5353

54+
DROP TABLE t;
5455
DROP EXTENSION aqo;

‎sql/look_a_like.sql

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ SET aqo.wide_search = 'on';
66

77
SET aqo.mode = 'learn';
88
SET aqo.show_details = 'on';
9-
set aqo.show_hash = 'off';
9+
SET aqo.show_hash = 'off';
1010
SET aqo.min_neighbors_for_predicting = 1;
11+
SET aqo.predict_with_few_neighbors = 'off';
1112
SET enable_nestloop = 'off';
1213
SET enable_mergejoin = 'off';
1314
SET enable_material = 'off';
@@ -142,10 +143,73 @@ FROM expln('
142143
SELECT * FROM (A LEFT JOIN B ON A.x1 = B.y1) sc left join C on sc.x1=C.z1;') AS str
143144
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
144145

146+
147+
-- Next few test cases focus on fss corresponding to (x1 > ? AND x2 < ? AND x3 < ?). We will denote
148+
-- it by fss0. At this moment there is exactly one fs with (fs, fss0, dbid) record in aqo_data. We'll
149+
-- refer to it as fs0.
150+
151+
-- Let's create another fs for fss0. We'll call this fs fs1. Since aqo.wide_search='on',
152+
-- aqo.min_neighbors_for_predicting=1, and there is (fs0, fss0, dbid) data record, AQO must be used here.
153+
SELECT str AS result
154+
FROM expln('
155+
SELECT * FROM A WHERE x1 > -100 AND x2 < 10 AND x3 < 10;') AS str
156+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
157+
-- Now there are 2 data records for fss0: one for (fs0, fss0, dbid) and one for (fs1, fss0, dbid)
158+
159+
-- We repeat previous query, but set aqo.min_neighbors_for_predicting to 2. Since aqo.predict_with_few_neighbors
160+
-- is 'off', AQO is obliged to use both data records for fss0.
161+
SET aqo.min_neighbors_for_predicting = 2;
162+
SELECT str AS result
163+
FROM expln('
164+
SELECT * FROM A WHERE x1 > 1 AND x2 < 10 AND x3 < 10;') AS str
165+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
166+
-- Now there are 3 data records for fss0: 1 for (fs0, fss0, dbid) and 2 for (fs1, fss0, dbid)
167+
168+
-- Lastly, we run invoke query with previously unseen fs with fss0 feature subspace. AQO must use
169+
-- three data records from two neighbors for this one.
170+
SET aqo.min_neighbors_for_predicting = 3;
171+
SELECT str AS result
172+
FROM expln('
173+
SELECT x2 FROM A WHERE x1 > 3 AND x2 < 10 AND x3 < 10 GROUP BY(x2);') AS str
174+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
175+
176+
-----
177+
DROP TABLE IF EXISTS t;
178+
CREATE TABLE t AS SELECT x, x AS y, x AS z FROM generate_series(1, 10000) x;
179+
ANALYZE t;
180+
SELECT true AS success FROM aqo_reset();
181+
182+
-- Test that when there are less records than aqo.min_neighbors_for_predicting for given (fs, fss, dbid)
183+
-- and aqo.predict_with_few_neighbors is off, those records have higher precedence for cardinality estimation
184+
-- than neighbors' records.
185+
SELECT str AS result
186+
FROM expln('
187+
select * from t where x <= 10000 and y <= 10000 and z <= 10000;') AS str
188+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
189+
DO
190+
$$
191+
BEGIN
192+
for counter in 1..20 loop
193+
EXECUTE format('explain analyze select *, 1 from t where x <= 1 and y <= 1 and z <= %L;', 10 * counter);
194+
EXECUTE format('explain analyze select *, 1 from t where x <= 1 and y <= %L and z <= 1;', 10 * counter);
195+
EXECUTE format('explain analyze select *, 1 from t where x <= %L and y <= 1 and z <= 1;', 10 * counter);
196+
end loop;
197+
END;
198+
$$ LANGUAGE PLPGSQL;
199+
-- AQO should predict ~1000 rows to indicate that the record from previous invocation was used.
200+
SELECT str AS result
201+
FROM expln('
202+
select * from t where x <= 10000 and y <= 10000 and z <= 10000;') AS str
203+
WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT LIKE '%Sort Method%';
204+
205+
145206
RESET aqo.wide_search;
207+
RESET aqo.predict_with_few_neighbors;
208+
RESET aqo.min_neighbors_for_predicting;
146209
DROP EXTENSION aqo CASCADE;
147210

148211
DROP TABLE a;
149212
DROP TABLE b;
150213
DROP TABLE c;
214+
DROP TABLE t;
151215
DROP FUNCTION expln;

‎storage.c

Lines changed: 41 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,6 @@ PG_FUNCTION_INFO_V1(aqo_query_stat_update);
120120
PG_FUNCTION_INFO_V1(aqo_data_update);
121121

122122

123-
bool
124-
load_fss_ext(uint64 fs, int fss, OkNNrdata *data, List **reloids)
125-
{
126-
return load_aqo_data(fs, fss, data, reloids, false, NULL);
127-
}
128-
129123
bool
130124
update_fss_ext(uint64 fs, int fss, OkNNrdata *data, List *reloids)
131125
{
@@ -1577,66 +1571,53 @@ fs_distance(double *a, double *b, int len)
15771571
}
15781572

15791573
static bool
1580-
nearest_neighbor(double **matrix, int old_rows, double *neibour, int cols)
1574+
nearest_neighbor(double **matrix, int old_rows, double *neighbor, int cols)
15811575
{
15821576
int i;
15831577
for (i=0; i<old_rows; i++)
15841578
{
1585-
if (fs_distance(neibour, matrix[i], cols) == 0)
1579+
if (fs_distance(neighbor, matrix[i], cols) == 0)
15861580
return true;
15871581
}
15881582
return false;
15891583
}
15901584

1585+
/*
1586+
* Append data records from temp_data to data.
1587+
* Repeated records (with same features) are skipped; data->rows is kept <= aqo_K.
1588+
*/
15911589
static void
1592-
build_knn_matrix(OkNNrdata *data, const OkNNrdata *temp_data, double *features)
1590+
update_knn_matrix(OkNNrdata *data, const OkNNrdata *temp_data)
15931591
{
1592+
int k = (data->rows < 0) ? 0 : data->rows;
1593+
int i;
1594+
15941595
Assert(data->cols == temp_data->cols);
15951596
Assert(data->matrix);
15961597

1597-
if (features != NULL)
1598+
if (data->cols > 0)
15981599
{
1599-
int old_rows = data->rows;
1600-
int k = (old_rows < 0) ? 0 : old_rows;
1601-
1602-
if (data->cols > 0)
1600+
for (i = 0; i < temp_data->rows && k < aqo_K; i++)
16031601
{
1604-
int i;
1605-
1606-
Assert(data->cols == temp_data->cols);
1607-
1608-
for (i = 0; i < temp_data->rows; i++)
1602+
if (!nearest_neighbor(data->matrix, k, temp_data->matrix[i], data->cols))
16091603
{
1610-
if (k < aqo_K && !nearest_neighbor(data->matrix, old_rows,
1611-
temp_data->matrix[i],
1612-
data->cols))
1613-
{
1614-
memcpy(data->matrix[k], temp_data->matrix[i], data->cols * sizeof(double));
1615-
data->rfactors[k] = temp_data->rfactors[i];
1616-
data->targets[k] = temp_data->targets[i];
1617-
k++;
1618-
}
1604+
memcpy(data->matrix[k], temp_data->matrix[i], data->cols * sizeof(double));
1605+
data->rfactors[k] = temp_data->rfactors[i];
1606+
data->targets[k] = temp_data->targets[i];
1607+
k++;
16191608
}
1620-
data->rows = k;
16211609
}
16221610
}
1623-
else
1611+
/* Data has no columns. Only one record can be added */
1612+
else if (k == 0 && temp_data->rows > 0)
16241613
{
1625-
if (data->rows > 0)
1626-
/* trivial strategy - use first suitable record and ignore others */
1627-
return;
1628-
memcpy(data, temp_data, sizeof(OkNNrdata));
1629-
if (data->cols > 0)
1630-
{
1631-
int i;
1632-
1633-
for (i = 0; i < data->rows; i++)
1634-
{
1635-
Assert(data->matrix[i]);
1636-
memcpy(data->matrix[i], temp_data->matrix[i], data->cols * sizeof(double));
1637-
}
1638-
}
1614+
data->rfactors[0] = temp_data->rfactors[0];
1615+
data->targets[0] = temp_data->targets[0];
1616+
k = 1;
16391617
}
1618+
data->rows = k;
1619+
1620+
Assert(data->rows >= 0 && data->rows <= aqo_K);
16401621
}
16411622

16421623
static OkNNrdata *
@@ -1706,20 +1687,19 @@ _fill_knn_data(const DataEntry *entry, List **reloids)
17061687
*
17071688
* If wideSearch is true - make seqscan on the hash table to see for relevant
17081689
* data across neighbours.
1709-
* If reloids is NULL - don't fill this list.
17101690
*
17111691
* Return false if the operation was unsuccessful.
17121692
*/
17131693
bool
1714-
load_aqo_data(uint64 fs, int fss, OkNNrdata *data, List **reloids,
1715-
bool wideSearch, double *features)
1694+
load_aqo_data(uint64 fs, int fss, OkNNrdata *data, bool wideSearch)
17161695
{
17171696
DataEntry *entry;
17181697
bool found;
17191698
data_key key = {.fs = fs, .fss = fss};
17201699
OkNNrdata *temp_data;
17211700

17221701
Assert(!LWLockHeldByMe(&aqo_state->data_lock));
1702+
Assert(wideSearch || data->rows <= 0);
17231703

17241704
dsa_init();
17251705

@@ -1739,16 +1719,16 @@ load_aqo_data(uint64 fs, int fss, OkNNrdata *data, List **reloids,
17391719
if (entry->cols != data->cols)
17401720
{
17411721
/* Collision happened? */
1742-
elog(LOG, "[AQO] Does a collision happened? Check it if possible "
1722+
elog(LOG, "[AQO] Did a collision happen? Check it if possible "
17431723
"(fs: "UINT64_FORMAT", fss: %d).",
17441724
fs, fss);
17451725
found = false; /* Sign of unsuccessful operation */
17461726
goto end;
17471727
}
17481728

1749-
temp_data = _fill_knn_data(entry, reloids);
1729+
temp_data = _fill_knn_data(entry, NULL);
17501730
Assert(temp_data->rows > 0);
1751-
build_knn_matrix(data, temp_data, features);
1731+
update_knn_matrix(data, temp_data);
17521732
Assert(data->rows > 0);
17531733
}
17541734
else
@@ -1770,28 +1750,31 @@ load_aqo_data(uint64 fs, int fss, OkNNrdata *data, List **reloids,
17701750

17711751
temp_data = _fill_knn_data(entry, &tmp_oids);
17721752

1773-
if (data->rows > 0 && list_length(tmp_oids) != noids)
1753+
if (noids >= 0 && list_length(tmp_oids) != noids)
17741754
{
17751755
/* Dubious case. So log it and skip these data */
17761756
elog(LOG,
17771757
"[AQO] different number depended oids for the same fss %d: "
17781758
"%d and %d correspondingly.",
17791759
fss, list_length(tmp_oids), noids);
1780-
Assert(noids >= 0);
17811760
list_free(tmp_oids);
17821761
continue;
17831762
}
17841763

17851764
noids = list_length(tmp_oids);
1765+
list_free(tmp_oids);
17861766

1787-
if (reloids != NULL && *reloids == NIL)
1788-
*reloids = tmp_oids;
1789-
else
1790-
list_free(tmp_oids);
1791-
1792-
build_knn_matrix(data, temp_data, NULL);
1767+
update_knn_matrix(data, temp_data);
17931768
found = true;
1769+
1770+
/* Abort if data is full */
1771+
if (data->rows == aqo_K || (data->cols == 0 && data->rows == 1))
1772+
{
1773+
hash_seq_term(&hash_seq);
1774+
break;
1775+
}
17941776
}
1777+
17951778
}
17961779

17971780
Assert(!found || (data->rows > 0 && data->rows <= aqo_K));

‎storage.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ extern void aqo_qtexts_load(void);
144144

145145
extern bool aqo_data_store(uint64 fs, int fss, AqoDataArgs *data,
146146
List *reloids);
147-
extern bool load_aqo_data(uint64 fs, int fss, OkNNrdata *data, List **reloids,
148-
bool wideSearch, double *features);
147+
extern bool load_aqo_data(uint64 fs, int fss, OkNNrdata *data, bool wideSearch);
149148
extern void aqo_data_flush(void);
150149
extern void aqo_data_load(void);
151150

@@ -166,7 +165,6 @@ extern bool query_is_deactivated(uint64 query_hash);
166165
extern void add_deactivated_query(uint64 query_hash);
167166

168167
/* Storage interaction */
169-
extern bool load_fss_ext(uint64 fs, int fss, OkNNrdata *data, List **reloids);
170168
extern bool update_fss_ext(uint64 fs, int fss, OkNNrdata *data, List *reloids);
171169

172170
extern bool update_query_timeout(uint64 queryid, int64 smart_timeout);

0 commit comments

Comments
 (0)
Please sign in to comment.