Commit cbfe6a5e authored by Sergei Petrunia's avatar Sergei Petrunia Committed by Sergei Golubchik

MDEV-26996 Support descending indexes in the range optimizer

- Code cleanup
- Disable "Using index for GROUP BY" over indexes with DESC keyparts
parent 3a82c256
...@@ -154,5 +154,28 @@ json_detailed(json_extract(trace, '$**.range_access_plan.ranges')) ...@@ -154,5 +154,28 @@ json_detailed(json_extract(trace, '$**.range_access_plan.ranges'))
"(4,80) <= (a,b) <= (2,50)" "(4,80) <= (a,b) <= (2,50)"
] ]
] ]
set optimizer_trace=default;
drop table t2; drop table t2;
#
# Check that "Using index for group-by" is disabled (it's not supported, yet)
#
CREATE TABLE t1 (p int NOT NULL, a int NOT NULL, PRIMARY KEY (p,a desc));
insert into t1 select 2,seq from seq_0_to_1000;
EXPLAIN select MIN(a) from t1 where p = 2 group by p;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref PRIMARY PRIMARY 4 const 1000 Using index
select json_detailed(json_extract(trace, '$**.potential_group_range_indexes'))
from information_schema.optimizer_trace;
json_detailed(json_extract(trace, '$**.potential_group_range_indexes'))
[
[
{
"index": "PRIMARY",
"usable": false,
"cause": "Reverse-ordered (not supported yet)"
}
]
]
drop table t1;
set optimizer_trace=default;
...@@ -73,5 +73,16 @@ select * from t2 where a between 2 and 4 and b between 50 and 80; ...@@ -73,5 +73,16 @@ select * from t2 where a between 2 and 4 and b between 50 and 80;
select json_detailed(json_extract(trace, '$**.range_access_plan.ranges')) select json_detailed(json_extract(trace, '$**.range_access_plan.ranges'))
from information_schema.optimizer_trace; from information_schema.optimizer_trace;
set optimizer_trace=default;
drop table t2; drop table t2;
--echo #
--echo # Check that "Using index for group-by" is disabled (it's not supported, yet)
--echo #
CREATE TABLE t1 (p int NOT NULL, a int NOT NULL, PRIMARY KEY (p,a desc));
insert into t1 select 2,seq from seq_0_to_1000;
EXPLAIN select MIN(a) from t1 where p = 2 group by p;
select json_detailed(json_extract(trace, '$**.potential_group_range_indexes'))
from information_schema.optimizer_trace;
drop table t1;
set optimizer_trace=default;
...@@ -1201,8 +1201,8 @@ EXPLAIN SELECT DISTINCT a FROM t1 { ...@@ -1201,8 +1201,8 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
}, },
{ {
"index": "a", "index": "a",
"key_parts": ["a"], "usable": true,
"usable": true "key_parts": ["a"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -1384,8 +1384,8 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a { ...@@ -1384,8 +1384,8 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "a", "index": "a",
"key_parts": ["a", "b", "c", "d"], "usable": true,
"usable": true "key_parts": ["a", "b", "c", "d"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -1583,8 +1583,8 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { ...@@ -1583,8 +1583,8 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "id", "index": "id",
"key_parts": ["id", "a"], "usable": true,
"usable": true "key_parts": ["id", "a"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -1771,8 +1771,8 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { ...@@ -1771,8 +1771,8 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "id", "index": "id",
"key_parts": ["id", "a"], "usable": true,
"usable": true "key_parts": ["id", "a"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -2010,13 +2010,13 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 { ...@@ -2010,13 +2010,13 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
}, },
{ {
"index": "a_c", "index": "a_c",
"key_parts": ["a", "c"], "usable": true,
"usable": true "key_parts": ["a", "c"]
}, },
{ {
"index": "a_b", "index": "a_b",
"key_parts": ["a", "b"], "usable": true,
"usable": true "key_parts": ["a", "b"]
} }
], ],
"setup_range_conditions": [], "setup_range_conditions": [],
...@@ -2213,8 +2213,8 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 { ...@@ -2213,8 +2213,8 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
}, },
{ {
"index": "a_c", "index": "a_c",
"key_parts": ["a", "c"], "usable": true,
"usable": true "key_parts": ["a", "c"]
}, },
{ {
"index": "a_b", "index": "a_b",
...@@ -3233,18 +3233,18 @@ explain select * from t1 where pk = 2 and a=5 and b=1 { ...@@ -3233,18 +3233,18 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "pk", "index": "pk",
"key_parts": ["pk"], "usable": true,
"usable": true "key_parts": ["pk"]
}, },
{ {
"index": "pk_a", "index": "pk_a",
"key_parts": ["pk", "a"], "usable": true,
"usable": true "key_parts": ["pk", "a"]
}, },
{ {
"index": "pk_a_b", "index": "pk_a_b",
"key_parts": ["pk", "a", "b"], "usable": true,
"usable": true "key_parts": ["pk", "a", "b"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -3751,8 +3751,8 @@ explain delete from t0 where t0.a<3 { ...@@ -3751,8 +3751,8 @@ explain delete from t0 where t0.a<3 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "a", "index": "a",
"key_parts": ["a"], "usable": true,
"usable": true "key_parts": ["a"]
} }
], ],
"setup_range_conditions": [], "setup_range_conditions": [],
...@@ -3889,8 +3889,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 { ...@@ -3889,8 +3889,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "a", "index": "a",
"key_parts": ["a"], "usable": true,
"usable": true "key_parts": ["a"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
...@@ -3954,8 +3954,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 { ...@@ -3954,8 +3954,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "a", "index": "a",
"key_parts": ["a"], "usable": true,
"usable": true "key_parts": ["a"]
} }
], ],
"best_covering_index_scan": { "best_covering_index_scan": {
......
...@@ -78,13 +78,13 @@ explain select * from t1 where a=1 or b=1 { ...@@ -78,13 +78,13 @@ explain select * from t1 where a=1 or b=1 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "a", "index": "a",
"key_parts": ["a"], "usable": true,
"usable": true "key_parts": ["a"]
}, },
{ {
"index": "b", "index": "b",
"key_parts": ["b"], "usable": true,
"usable": true "key_parts": ["b"]
}, },
{ {
"index": "c", "index": "c",
......
...@@ -93,13 +93,13 @@ explain select * from t1 where pk1 != 0 and key1 = 1 { ...@@ -93,13 +93,13 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"potential_range_indexes": [ "potential_range_indexes": [
{ {
"index": "PRIMARY", "index": "PRIMARY",
"key_parts": ["pk1", "pk2"], "usable": true,
"usable": true "key_parts": ["pk1", "pk2"]
}, },
{ {
"index": "key1", "index": "key1",
"key_parts": ["key1"], "usable": true,
"usable": true "key_parts": ["key1"]
}, },
{ {
"index": "key2", "index": "key2",
......
...@@ -2809,12 +2809,11 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2809,12 +2809,11 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
trace_idx_details.add("usable", false).add("cause", "fulltext"); trace_idx_details.add("usable", false).add("cause", "fulltext");
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
} }
trace_idx_details.add("usable", true);
param.key[param.keys]=key_parts; param.key[param.keys]=key_parts;
key_part_info= key_info->key_part; key_part_info= key_info->key_part;
uint cur_key_len= 0; uint cur_key_len= 0;
Json_writer_array trace_keypart(thd, "key_parts"); Json_writer_array trace_keypart(thd, "key_parts");
bool unusable_has_desc_keyparts= false;
for (uint part= 0 ; part < n_key_parts ; for (uint part= 0 ; part < n_key_parts ;
part++, key_parts++, key_part_info++) part++, key_parts++, key_part_info++)
{ {
...@@ -2829,18 +2828,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2829,18 +2828,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
/* Only HA_PART_KEY_SEG is used */ /* Only HA_PART_KEY_SEG is used */
key_parts->flag= (uint8) key_part_info->key_part_flag; key_parts->flag= (uint8) key_part_info->key_part_flag;
if (key_part_info->key_part_flag & HA_REVERSE_SORT)
unusable_has_desc_keyparts= true;
trace_keypart.add(key_parts->field->field_name); trace_keypart.add(key_parts->field->field_name);
} }
trace_keypart.end(); trace_keypart.end();
trace_idx_details.add("usable", !unusable_has_desc_keyparts);
unusable_has_desc_keyparts= false;
if (unusable_has_desc_keyparts) // TODO MDEV-13756
{
key_parts= param.key[param.keys];
continue;
}
param.real_keynr[param.keys++]=idx; param.real_keynr[param.keys++]=idx;
if (cur_key_len > max_key_len) if (cur_key_len > max_key_len)
max_key_len= cur_key_len; max_key_len= cur_key_len;
...@@ -13837,6 +13827,17 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) ...@@ -13837,6 +13827,17 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
goto next_index; goto next_index;
} }
{
for (uint i= 0; i < table->actual_n_key_parts(cur_index_info); i++)
{
if (cur_index_info->key_part[i].key_part_flag & HA_REVERSE_SORT)
{
cause="Reverse-ordered (not supported yet)";
goto next_index;
}
}
}
/* /*
This function is called on the precondition that the index is covering. This function is called on the precondition that the index is covering.
Therefore if the GROUP BY list contains more elements than the index, Therefore if the GROUP BY list contains more elements than the index,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment