Skip to content

Commit 1976b9a

Browse files
committed
[BACKPORT 2024.1][yugabyte#22772] YSQL: Fix CBO bug in the presence of hash indexes with included columns
Summary: Original commit: 67026c2 / D37594 This change fixes a bug found when costing an index scan on a hash index with included columns using CBO. Before this change, `yb_cost_index` allocated a list of clauses `index_conditions_on_each_column` of length `index->nkeycolumns`. However, there is code that traverses this list of clauses and assumes the length of this list if `index->ncolumns` which is wrong when the index in question has non-key columns. This simple change fixes this bug. This change also separates the regress test `yb_planner_base_scans_cost_model` into `yb_planner_base_scans_cost_model` and `yb_planner_base_scans_cost_model_colocated`. Before this change, everything in `yb_planner_base_scans_cost_model` belonged to a colocated database. This fixes a bug introduced in D33477/ec0126016f6a7ed403cf60c4894534c496bd6c41 in version 2024.1 Jira: DB-11675 Test Plan: ./yb_build.sh --java-test 'org.yb.pgsql.TestPgRegressPlanner' Reviewers: mtakahara, mihnea Reviewed By: mtakahara Subscribers: yql Differential Revision: https://phorge.dev.yugabyte.com/D37700
1 parent 01c8e67 commit 1976b9a

File tree

6 files changed

+148
-119
lines changed

6 files changed

+148
-119
lines changed

src/postgres/src/backend/optimizer/path/costsize.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7009,7 +7009,7 @@ yb_cost_index(IndexPath *path, PlannerInfo *root, double loop_count,
70097009
*/
70107010
list_free(index_conditions);
70117011
index_conditions = NIL;
7012-
for (int index_col = 0; index_col < index->ncolumns; ++index_col)
7012+
for (int index_col = 0; index_col < index->nkeycolumns; ++index_col)
70137013
{
70147014
if (list_length(index_conditions_on_each_column[index_col]) > 0)
70157015
{
Lines changed: 16 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,18 @@
1-
CREATE DATABASE base_scans_cost_model WITH COLOCATION = TRUE;
2-
\c base_scans_cost_model
1+
-- This file tests the YB CBO base scans cost model in non-colocated tables.
32
SET yb_enable_base_scans_cost_model = ON;
43
SET yb_enable_optimizer_statistics = ON;
5-
-- #18689 : Occasional SIGSEGV in queries with inequality filters on multiple
6-
-- index columns
7-
CREATE TABLE test_18689 (k1 INT, k2 INT, k3 INT, PRIMARY KEY (k1, k2, k3));
8-
INSERT INTO test_18689 (SELECT s, s, s FROM generate_series(1, 10000) s);
9-
ANALYZE test_18689;
10-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10;
11-
count
12-
-------
13-
4
14-
(1 row)
15-
16-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5;
17-
count
18-
-------
19-
4
20-
(1 row)
21-
22-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10;
23-
count
24-
-------
25-
4
26-
(1 row)
27-
28-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5;
29-
count
30-
-------
31-
4
32-
(1 row)
33-
34-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5 and k3 < 10;
35-
count
36-
-------
37-
4
38-
(1 row)
39-
40-
-- #20892 : Divide by 0 error in some queries with new cost model when yb_fetch_size_limit is enforced
41-
CREATE TABLE test_20892 (k INT, v VARCHAR(1024));
42-
INSERT INTO test_20892 (SELECT s, repeat(md5(s::text), 32) FROM generate_series(1, 100) s);
43-
ANALYZE test_20892;
44-
set yb_fetch_row_limit = 1024;
45-
set yb_fetch_size_limit = '1MB';
46-
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
47-
QUERY PLAN
48-
--------------------------------------------------
49-
Seq Scan on test_20892 (actual rows=100 loops=1)
50-
(1 row)
51-
52-
SELECT count(*) FROM test_20892;
53-
count
54-
-------
55-
100
56-
(1 row)
57-
58-
\d test_20892
59-
Table "public.test_20892"
60-
Column | Type | Collation | Nullable | Default
61-
--------+-------------------------+-----------+----------+---------
62-
k | integer | | |
63-
v | character varying(1024) | | |
64-
Colocation: true
65-
66-
set yb_fetch_row_limit = 100;
67-
set yb_fetch_size_limit = '10kB';
68-
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
69-
QUERY PLAN
70-
--------------------------------------------------
71-
Seq Scan on test_20892 (actual rows=100 loops=1)
72-
(1 row)
73-
74-
SELECT count(*) FROM test_20892;
75-
count
76-
-------
77-
100
78-
(1 row)
79-
80-
\d test_20892
81-
Table "public.test_20892"
82-
Column | Type | Collation | Nullable | Default
83-
--------+-------------------------+-----------+----------+---------
84-
k | integer | | |
85-
v | character varying(1024) | | |
86-
Colocation: true
87-
88-
DROP TABLE test_20892;
4+
CREATE TABLE test (v1 INT, v2 INT, v3 INT);
5+
CREATE INDEX test_index ON test ((v1) HASH, v2 ASC) INCLUDE (v3);
6+
EXPLAIN (COSTS OFF) SELECT * FROM test WHERE v2 > 100;
7+
QUERY PLAN
8+
------------------------------------------
9+
Index Only Scan using test_index on test
10+
Index Cond: (v2 > 100)
11+
(2 rows)
12+
13+
SELECT * FROM test WHERE v2 > 100;
14+
v1 | v2 | v3
15+
----+----+----
16+
(0 rows)
17+
18+
DROP TABLE test;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
-- This file tests the YB CBO base scans cost model in colocated tables.
2+
CREATE DATABASE base_scans_cost_model WITH COLOCATION = TRUE;
3+
\c base_scans_cost_model
4+
SET yb_enable_base_scans_cost_model = ON;
5+
SET yb_enable_optimizer_statistics = ON;
6+
-- #18689 : Occasional SIGSEGV in queries with inequality filters on multiple
7+
-- index columns
8+
CREATE TABLE test_18689 (k1 INT, k2 INT, k3 INT, PRIMARY KEY (k1, k2, k3));
9+
INSERT INTO test_18689 (SELECT s, s, s FROM generate_series(1, 10000) s);
10+
ANALYZE test_18689;
11+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10;
12+
count
13+
-------
14+
4
15+
(1 row)
16+
17+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5;
18+
count
19+
-------
20+
4
21+
(1 row)
22+
23+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10;
24+
count
25+
-------
26+
4
27+
(1 row)
28+
29+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5;
30+
count
31+
-------
32+
4
33+
(1 row)
34+
35+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5 and k3 < 10;
36+
count
37+
-------
38+
4
39+
(1 row)
40+
41+
-- #20892 : Divide by 0 error in some queries with new cost model when yb_fetch_size_limit is enforced
42+
CREATE TABLE test_20892 (k INT, v VARCHAR(1024));
43+
INSERT INTO test_20892 (SELECT s, repeat(md5(s::text), 32) FROM generate_series(1, 100) s);
44+
ANALYZE test_20892;
45+
set yb_fetch_row_limit = 1024;
46+
set yb_fetch_size_limit = '1MB';
47+
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
48+
QUERY PLAN
49+
--------------------------------------------------
50+
Seq Scan on test_20892 (actual rows=100 loops=1)
51+
(1 row)
52+
53+
SELECT count(*) FROM test_20892;
54+
count
55+
-------
56+
100
57+
(1 row)
58+
59+
\d test_20892
60+
Table "public.test_20892"
61+
Column | Type | Collation | Nullable | Default
62+
--------+-------------------------+-----------+----------+---------
63+
k | integer | | |
64+
v | character varying(1024) | | |
65+
Colocation: true
66+
67+
set yb_fetch_row_limit = 100;
68+
set yb_fetch_size_limit = '10kB';
69+
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
70+
QUERY PLAN
71+
--------------------------------------------------
72+
Seq Scan on test_20892 (actual rows=100 loops=1)
73+
(1 row)
74+
75+
SELECT count(*) FROM test_20892;
76+
count
77+
-------
78+
100
79+
(1 row)
80+
81+
\d test_20892
82+
Table "public.test_20892"
83+
Column | Type | Collation | Nullable | Default
84+
--------+-------------------------+-----------+----------+---------
85+
k | integer | | |
86+
v | character varying(1024) | | |
87+
Colocation: true
88+
89+
DROP TABLE test_20892;
Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,8 @@
1-
CREATE DATABASE base_scans_cost_model WITH COLOCATION = TRUE;
2-
\c base_scans_cost_model
3-
1+
-- This file tests the YB CBO base scans cost model in non-colocated tables.
42
SET yb_enable_base_scans_cost_model = ON;
53
SET yb_enable_optimizer_statistics = ON;
6-
7-
-- #18689 : Occasional SIGSEGV in queries with inequality filters on multiple
8-
-- index columns
9-
CREATE TABLE test_18689 (k1 INT, k2 INT, k3 INT, PRIMARY KEY (k1, k2, k3));
10-
INSERT INTO test_18689 (SELECT s, s, s FROM generate_series(1, 10000) s);
11-
ANALYZE test_18689;
12-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10;
13-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5;
14-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10;
15-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5;
16-
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5 and k3 < 10;
17-
18-
-- #20892 : Divide by 0 error in some queries with new cost model when yb_fetch_size_limit is enforced
19-
CREATE TABLE test_20892 (k INT, v VARCHAR(1024));
20-
INSERT INTO test_20892 (SELECT s, repeat(md5(s::text), 32) FROM generate_series(1, 100) s);
21-
ANALYZE test_20892;
22-
set yb_fetch_row_limit = 1024;
23-
set yb_fetch_size_limit = '1MB';
24-
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
25-
SELECT count(*) FROM test_20892;
26-
\d test_20892
27-
28-
set yb_fetch_row_limit = 100;
29-
set yb_fetch_size_limit = '10kB';
30-
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
31-
SELECT count(*) FROM test_20892;
32-
\d test_20892
33-
34-
DROP TABLE test_20892;
4+
CREATE TABLE test (v1 INT, v2 INT, v3 INT);
5+
CREATE INDEX test_index ON test ((v1) HASH, v2 ASC) INCLUDE (v3);
6+
EXPLAIN (COSTS OFF) SELECT * FROM test WHERE v2 > 100;
7+
SELECT * FROM test WHERE v2 > 100;
8+
DROP TABLE test;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
-- This file tests the YB CBO base scans cost model in colocated tables.
2+
CREATE DATABASE base_scans_cost_model WITH COLOCATION = TRUE;
3+
\c base_scans_cost_model
4+
5+
SET yb_enable_base_scans_cost_model = ON;
6+
SET yb_enable_optimizer_statistics = ON;
7+
8+
-- #18689 : Occasional SIGSEGV in queries with inequality filters on multiple
9+
-- index columns
10+
CREATE TABLE test_18689 (k1 INT, k2 INT, k3 INT, PRIMARY KEY (k1, k2, k3));
11+
INSERT INTO test_18689 (SELECT s, s, s FROM generate_series(1, 10000) s);
12+
ANALYZE test_18689;
13+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10;
14+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5;
15+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10;
16+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5;
17+
/*+ IndexScan(test_18689) */ SELECT count(*) FROM test_18689 WHERE k1 > 5 and k1 < 10 and k2 > 5 and k2 < 10 and k3 > 5 and k3 < 10;
18+
19+
-- #20892 : Divide by 0 error in some queries with new cost model when yb_fetch_size_limit is enforced
20+
CREATE TABLE test_20892 (k INT, v VARCHAR(1024));
21+
INSERT INTO test_20892 (SELECT s, repeat(md5(s::text), 32) FROM generate_series(1, 100) s);
22+
ANALYZE test_20892;
23+
set yb_fetch_row_limit = 1024;
24+
set yb_fetch_size_limit = '1MB';
25+
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
26+
SELECT count(*) FROM test_20892;
27+
\d test_20892
28+
29+
set yb_fetch_row_limit = 100;
30+
set yb_fetch_size_limit = '10kB';
31+
explain (analyze, costs off, summary off, timing off) SELECT 0 FROM test_20892;
32+
SELECT count(*) FROM test_20892;
33+
\d test_20892
34+
35+
DROP TABLE test_20892;

src/postgres/src/test/regress/yb_planner_serial_schedule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ test: yb_planner_joins
88
test: yb_planner_join_order
99
test: yb_planner_size_estimates
1010
test: yb_planner_heuristic_selectivity
11+
test: yb_planner_base_scans_cost_model_colocated
1112
test: yb_planner_base_scans_cost_model

0 commit comments

Comments
 (0)