mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +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:
|
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
|
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;
|
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;
|
EXPLAIN EXTENDED DELETE /*+ NO_INDEX(t1 i_ab) */ FROM t1 WHERE a = 1 AND b = 2 AND c = 3;
|
||||||
|
|
||||||
DROP TABLE t1;
|
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.
|
fixing the child objects.
|
||||||
*/
|
*/
|
||||||
set_fixed();
|
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. */
|
/* Make sure that adjustment is called only once. */
|
||||||
DBUG_ASSERT(keyinfo_array.size() == 0);
|
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())
|
if (are_children_fully_fixed())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@@ -648,10 +648,12 @@ public:
|
|||||||
|
|
||||||
void set_fixed() { fixed= true; }
|
void set_fixed() { fixed= true; }
|
||||||
bool is_fixed() const { return fixed; }
|
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); }
|
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_set_key_map(uint i) { return key_map.is_set(i); }
|
||||||
bool is_key_map_clear_all() { return key_map.is_clear_all(); }
|
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; }
|
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(
|
const Lex_ident_sys key_conflict(
|
||||||
STRING_WITH_LEN("another hint was already specified for this index"));
|
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;
|
uint warn_code= 0;
|
||||||
if (is_compound_hint(hint_type) &&
|
if (is_compound_hint(hint_type) &&
|
||||||
|
@@ -656,6 +656,14 @@ public:
|
|||||||
public:
|
public:
|
||||||
using AND4::AND4;
|
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;
|
bool resolve(Parse_context *pc) const;
|
||||||
void append_args(THD *thd, String *str) const override;
|
void append_args(THD *thd, String *str) const override;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user