mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-37292 Hint NO_INDEX() disables all indexes if none of given index names is resolved
When a hint has a list of index names, for example, `NO_INDEX(t1 idx1, idx2)` there is a possibility that some or all of the listed index names will not be resolved. If none of them are resolved, the hint becomes a table-level hint, for example, `NO_INDEX(t1)`, which erroneously disables all indexes of `t1` instead of disabling only some of them. This commit addresses this issue by adding an additional check: a hint containing a list of index names is considered resolved only when at least one of the listed names is resolved successfully.
This commit is contained in:
committed by
Sergei Golubchik
parent
c329c43be7
commit
893761b35c
@@ -272,3 +272,96 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
Warnings:
|
||||
Note 1003 delete /*+ NO_INDEX(`t1`@`select#1` `i_ab`) */ from `test`.`t1` using dual where `test`.`t1`.`a` = 1 and `test`.`t1`.`b` = 2 and `test`.`t1`.`c` = 3
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Hint NO_INDEX() disables all indexes if none of given index names is not resolved
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
PRIMARY KEY(a),
|
||||
KEY ab(a, b)
|
||||
);
|
||||
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4);
|
||||
ANALYZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status Engine-independent statistics collected
|
||||
test.t1 analyze status OK
|
||||
# By default, the index `ab` is used for grouping
|
||||
EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
# Invalid index names are ignored, index `ab` is still used
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint
|
||||
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
# This hint disables all indexes for grouping, so effectively it is the same
|
||||
# as table-level hint NO_GROUP_INDEX(t1)
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `dcba` for NO_GROUP_INDEX hint
|
||||
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1` `bbb`,`dcba`,`PRIMARY`,`ab`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
# Compare the previous case with the table-level hint, results are the same:
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
# Same set of tests as above but for the global `NO_INDEX()` hint
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
|
||||
Note 1003 select /*+ NO_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort
|
||||
Warnings:
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
|
||||
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
|
||||
Note 1003 select /*+ NO_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`,`ab`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 12.1 tests
|
||||
#
|
||||
|
@@ -112,3 +112,48 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a = 1 AND b = 2 AND c = 3;
|
||||
EXPLAIN EXTENDED DELETE /*+ NO_INDEX(t1 i_ab) */ FROM t1 WHERE a = 1 AND b = 2 AND c = 3;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Hint NO_INDEX() disables all indexes if none of given index names is not resolved
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
PRIMARY KEY(a),
|
||||
KEY ab(a, b)
|
||||
);
|
||||
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4);
|
||||
|
||||
ANALYZE TABLE t1;
|
||||
|
||||
# Warnings "Unresolved table/index name..." are generated during both prepare
|
||||
# and execution stages. So disable PS protocol to avoid duplication
|
||||
--disable_ps_protocol
|
||||
|
||||
--echo # By default, the index `ab` is used for grouping
|
||||
EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a;
|
||||
--echo # Invalid index names are ignored, index `ab` is still used
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
|
||||
|
||||
--echo # This hint disables all indexes for grouping, so effectively it is the same
|
||||
--echo # as table-level hint NO_GROUP_INDEX(t1)
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
|
||||
--echo # Compare the previous case with the table-level hint, results are the same:
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a;
|
||||
|
||||
--echo # Same set of tests as above but for the global `NO_INDEX()` hint
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
|
||||
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a;
|
||||
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 12.1 tests
|
||||
--echo #
|
||||
|
@@ -552,14 +552,6 @@ bool Opt_hints_table::fix_key_hints(TABLE *table)
|
||||
fixing the child objects.
|
||||
*/
|
||||
set_fixed();
|
||||
if (is_specified(INDEX_HINT_ENUM))
|
||||
global_index_map.set_fixed();
|
||||
if (is_specified(JOIN_INDEX_HINT_ENUM))
|
||||
join_index_map.set_fixed();
|
||||
if (is_specified(GROUP_INDEX_HINT_ENUM))
|
||||
group_index_map.set_fixed();
|
||||
if (is_specified(ORDER_INDEX_HINT_ENUM))
|
||||
order_index_map.set_fixed();
|
||||
|
||||
/* Make sure that adjustment is called only once. */
|
||||
DBUG_ASSERT(keyinfo_array.size() == 0);
|
||||
@@ -582,6 +574,26 @@ bool Opt_hints_table::fix_key_hints(TABLE *table)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fixing compound index hints. A compound hint is fixed in two cases:
|
||||
- it is a table-level hint, i.e. does not have a list of index names
|
||||
(like ORDER_INDEX(t1);
|
||||
- it has a list of index names, and at least one of listed
|
||||
index names is resolved successfully. So, NO_INDEX(t1 bad_idx) does not
|
||||
become a table-level hint NO_INDEX(t1) if `bad_idx` cannnot be resolved.
|
||||
*/
|
||||
for (opt_hints_enum
|
||||
hint_type : { INDEX_HINT_ENUM, JOIN_INDEX_HINT_ENUM,
|
||||
GROUP_INDEX_HINT_ENUM, ORDER_INDEX_HINT_ENUM })
|
||||
{
|
||||
if (is_specified(hint_type))
|
||||
{
|
||||
Opt_hints_key_bitmap *bitmap= get_key_hint_bitmap(hint_type);
|
||||
if (bitmap->is_table_level() || bitmap->bits_set() > 0)
|
||||
bitmap->set_fixed();
|
||||
}
|
||||
}
|
||||
|
||||
if (are_children_fully_fixed())
|
||||
return false;
|
||||
|
||||
|
@@ -648,10 +648,12 @@ public:
|
||||
|
||||
void set_fixed() { fixed= true; }
|
||||
bool is_fixed() const { return fixed; }
|
||||
bool is_table_level() const { return parsed_hint->is_table_level_hint(); }
|
||||
|
||||
void set_key_map(uint i) { key_map.set_bit(i); }
|
||||
bool is_set_key_map(uint i) { return key_map.is_set(i); }
|
||||
bool is_key_map_clear_all() { return key_map.is_clear_all(); }
|
||||
uint bits_set() { return key_map.bits_set(); }
|
||||
Key_map *get_key_map() { return &key_map; }
|
||||
};
|
||||
|
||||
|
@@ -588,7 +588,13 @@ bool Parser::Index_level_hint::resolve(Parse_context *pc) const
|
||||
const Lex_ident_sys key_conflict(
|
||||
STRING_WITH_LEN("another hint was already specified for this index"));
|
||||
|
||||
if (is_empty()) // Empty list of index names, i.e. it is a table level hint
|
||||
/*
|
||||
If no index names are given, this is a table level hint, for example:
|
||||
GROUP_INDEX(t1), NO_MRR(t2).
|
||||
Otherwise this is a group of index-level hints:
|
||||
NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c)
|
||||
*/
|
||||
if (is_empty())
|
||||
{
|
||||
uint warn_code= 0;
|
||||
if (is_compound_hint(hint_type) &&
|
||||
|
@@ -656,6 +656,14 @@ public:
|
||||
public:
|
||||
using AND4::AND4;
|
||||
|
||||
/*
|
||||
If no index names are given, this is a table level hint, for example:
|
||||
GROUP_INDEX(t1), NO_MRR(t2).
|
||||
Otherwise this is an index-level hints:
|
||||
NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c)
|
||||
*/
|
||||
bool is_table_level_hint() const { return is_empty(); }
|
||||
|
||||
bool resolve(Parse_context *pc) const;
|
||||
void append_args(THD *thd, String *str) const override;
|
||||
};
|
||||
|
Reference in New Issue
Block a user