Skip to content

Commit 877e4a3

Browse files
committed
MDEV-33281 Implement optimizer hints
This commit introduces: - the infrastructure for optimizer hints; - hints for join buffering: BNL(), NO_BNL(), BKA(), NO_BKA(); - NO_ICP() hint for disabling index condition pushdown; - MRR(), MO_MRR() hint for multi-range reads control; - NO_RANGE_OPTIMIZATION() for disabling range optimization; - QB_NAME() for assigning names for query blocks.
1 parent 6340c23 commit 877e4a3

21 files changed

+1555
-64
lines changed

libmysqld/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
160160
../sql/sp_cursor.cc
161161
../sql/opt_hints_parser.cc ../sql/opt_hints_parser.h
162162
../sql/scan_char.h
163+
../sql/opt_hints.cc ../sql/opt_hints.h
163164
${GEN_SOURCES}
164165
${MYSYS_LIBWRAP_SOURCE}
165166
)

mysql-test/main/opt_hints.result

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
139139
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
140140
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
141141
Warnings:
142-
Warning 4199 Unresolved name `t5`@`select#2` `z_idx` for NO_ICP hint
142+
Warning 4205 Unresolved index name `t5`@`select#2` `z_idx` for NO_ICP hint
143143
Note 1003 select /*+ NO_ICP(`t5`@`select#2` `y_idx`) NO_ICP(`t5`@`select#2` `x_idx`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0)
144144
# ICP should still be used
145145
EXPLAIN EXTENDED SELECT * FROM
@@ -405,7 +405,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
405405
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
406406
1 SIMPLE t2 ALL f1 NULL NULL NULL 28 25.00 Using where; Using join buffer (flat, BNL join)
407407
Warnings:
408-
Warning 4198 Query block name `qb1` is not found for BKA hint
408+
Warning 4203 Query block name `qb1` is not found for BKA hint
409409
Note 1003 select /*+ QB_NAME(`qb1`) */ `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`f1` = `test`.`t1`.`f1` and `test`.`t2`.`f2` between `test`.`t1`.`f1` and `test`.`t1`.`f2` and `test`.`t2`.`f2` + 1 >= `test`.`t1`.`f1` + 1
410410
# Should not crash
411411
PREPARE stmt1 FROM "SELECT /*+ BKA(t2) */ t2.f1, t2.f2, t2.f3 FROM t1,t2
@@ -449,9 +449,9 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
449449
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
450450
1 SIMPLE t2 ALL f1 NULL NULL NULL 28 25.00 Using where; Using join buffer (flat, BNL join)
451451
Warnings:
452-
Warning 4199 Unresolved name `t3`@`select#1` for BKA hint
453-
Warning 4199 Unresolved name `t3`@`select#1` for NO_RANGE_OPTIMIZATION hint
454-
Warning 4199 Unresolved name `t3`@`select#1` `idx1` for NO_RANGE_OPTIMIZATION hint
452+
Warning 4204 Unresolved table name `t3`@`select#1` for BKA hint
453+
Warning 4204 Unresolved table name `t3`@`select#1` for NO_RANGE_OPTIMIZATION hint
454+
Warning 4205 Unresolved index name `t3`@`select#1` `idx1` for NO_RANGE_OPTIMIZATION hint
455455
Note 1003 select /*+ BKA(`t2`@`select#1`) NO_BNL(`t1`@`select#1`) */ `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`f1` = `test`.`t1`.`f1` and `test`.`t2`.`f2` between `test`.`t1`.`f1` and `test`.`t1`.`f2` and `test`.`t2`.`f2` + 1 >= `test`.`t1`.`f1` + 1
456456
# Check illegal syntax
457457
EXPLAIN EXTENDED SELECT /*+ BKA(qb1 t3@qb1) */ f2 FROM
@@ -488,7 +488,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
488488
1 SIMPLE tbl12 ALL NULL NULL NULL NULL 10 100.00 Using where
489489
1 SIMPLE tbl13 hash_ALL a #hash#a 5 test.tbl12.a 1000 0.10 Using where; Using join buffer (flat, BNLH join)
490490
Warnings:
491-
Warning 4199 Unresolved name `tbl2`@`select#1` for BKA hint
491+
Warning 4204 Unresolved table name `tbl2`@`select#1` for BKA hint
492492
Note 1003 select `test`.`tbl12`.`a` AS `a`,`test`.`tbl12`.`b` AS `b`,`test`.`tbl13`.`a` AS `a`,`test`.`tbl13`.`b` AS `b`,`test`.`tbl13`.`c` AS `c`,`test`.`tbl13`.`filler` AS `filler` from `test`.`t12` `tbl12` join `test`.`t13` `tbl13` where `test`.`tbl13`.`a` = `test`.`tbl12`.`a` and `test`.`tbl13`.`b` + 1 <= `test`.`tbl13`.`b` + 1
493493
# Check that PS and conventional statements give the same result.
494494
FLUSH STATUS;
@@ -930,19 +930,19 @@ SELECT /*+ BKA() BKA() */ 1;
930930
1
931931
1
932932
Warnings:
933-
Warning 4197 Hint BKA( ) is ignored as conflicting/duplicated
933+
Warning 4202 Hint BKA() is ignored as conflicting/duplicated
934934
SELECT /*+ BKA(t1) BKA(t1) */ * FROM t1;
935935
i
936936
Warnings:
937-
Warning 4197 Hint BKA(`t1` ) is ignored as conflicting/duplicated
937+
Warning 4202 Hint BKA(`t1`) is ignored as conflicting/duplicated
938938
SELECT /*+ QB_NAME(q1) BKA(t1@q1) BKA(t1@q1) */ * FROM t1;
939939
i
940940
Warnings:
941-
Warning 4197 Hint BKA(`t1`@`q1` ) is ignored as conflicting/duplicated
941+
Warning 4202 Hint BKA(`t1`@`q1`) is ignored as conflicting/duplicated
942942
SELECT /*+ QB_NAME(q1) NO_ICP(@q1 t1 PRIMARY) NO_ICP(@q1 t1 PRIMARY) */ * FROM t1;
943943
i
944944
Warnings:
945-
Warning 4197 Hint NO_ICP(`t1`@`q1` `PRIMARY` ) is ignored as conflicting/duplicated
945+
Warning 4202 Hint NO_ICP(`t1`@`q1` `PRIMARY`) is ignored as conflicting/duplicated
946946
DROP TABLE t1;
947947
# WL#8016 Parser for optimizer hints
948948
CREATE TABLE t1 (i INT, j INT);
@@ -955,12 +955,12 @@ SELECT /*+*/ 1;
955955
1
956956
1
957957
Warnings:
958-
Warning 1064 Optimizer hint syntax error near '*/' at line 1
958+
Warning 1064 Optimizer hint syntax error near '*/ 1' at line 1
959959
SELECT /*+ */ 1;
960960
1
961961
1
962962
Warnings:
963-
Warning 1064 Optimizer hint syntax error near '*/' at line 1
963+
Warning 1064 Optimizer hint syntax error near '*/ 1' at line 1
964964
SELECT /*+ * ** / // /* */ 1;
965965
1
966966
1
@@ -990,22 +990,22 @@ SELECT /*+ `@` */ 1;
990990
1
991991
1
992992
Warnings:
993-
Warning 1064 Optimizer hint syntax error near '@` */ 1' at line 1
993+
Warning 1064 Optimizer hint syntax error near '`@` */ 1' at line 1
994994
SELECT /*+ `@foo` */ 1;
995995
1
996996
1
997997
Warnings:
998-
Warning 1064 Optimizer hint syntax error near '@foo` */ 1' at line 1
998+
Warning 1064 Optimizer hint syntax error near '`@foo` */ 1' at line 1
999999
SELECT /*+ `foo@bar` */ 1;
10001000
1
10011001
1
10021002
Warnings:
1003-
Warning 1064 Optimizer hint syntax error near 'foo@bar` */ 1' at line 1
1003+
Warning 1064 Optimizer hint syntax error near '`foo@bar` */ 1' at line 1
10041004
SELECT /*+ `foo @bar` */ 1;
10051005
1
10061006
1
10071007
Warnings:
1008-
Warning 1064 Optimizer hint syntax error near 'foo @bar` */ 1' at line 1
1008+
Warning 1064 Optimizer hint syntax error near '`foo @bar` */ 1' at line 1
10091009
SELECT /*+ BKA( @) */ 1;
10101010
1
10111011
1
@@ -1020,7 +1020,7 @@ SELECT /*+ BKA(t1 @) */ 1;
10201020
1
10211021
1
10221022
Warnings:
1023-
Warning 1064 Optimizer hint syntax error near '@) */ 1' at line 1
1023+
Warning 1064 Optimizer hint syntax error near ') */ 1' at line 1
10241024

10251025
# We don't support "*/" inside quoted identifiers (syntax error):
10261026

@@ -1079,15 +1079,15 @@ Warning 1064 Optimizer hint syntax error near 'b) */ 1 FROM t1 a, t1 b' at lin
10791079
SELECT /*+ NO_ICP(i1) */ 1 FROM t1;
10801080
1
10811081
Warnings:
1082-
Warning 4199 Unresolved name `i1`@`select#1` for NO_ICP hint
1082+
Warning 4204 Unresolved table name `i1`@`select#1` for NO_ICP hint
10831083
SELECT /*+ NO_ICP(i1 i2) */ 1 FROM t1;
10841084
1
10851085
Warnings:
1086-
Warning 4199 Unresolved name `i1`@`select#1` `i2` for NO_ICP hint
1086+
Warning 4205 Unresolved index name `i1`@`select#1` `i2` for NO_ICP hint
10871087
SELECT /*+ NO_ICP(@qb ident) */ 1 FROM t1;
10881088
1
10891089
Warnings:
1090-
Warning 4198 Query block name `qb` is not found for NO_ICP hint
1090+
Warning 4203 Query block name `qb` is not found for NO_ICP hint
10911091

10921092
# valid hint sequences, no warnings expected:
10931093

@@ -1142,12 +1142,12 @@ CREATE INDEX 3rd_index ON t1(i, j);
11421142
SELECT /*+ NO_ICP(3rd_index) */ 1 FROM t1;
11431143
1
11441144
Warnings:
1145-
Warning 4199 Unresolved name `3rd_index`@`select#1` for NO_ICP hint
1145+
Warning 4204 Unresolved table name `3rd_index`@`select#1` for NO_ICP hint
11461146
CREATE INDEX $index ON t1(j, i);
11471147
SELECT /*+ NO_ICP($index) */ 1 FROM t1;
11481148
1
11491149
Warnings:
1150-
Warning 4199 Unresolved name `$index`@`select#1` for NO_ICP hint
1150+
Warning 4204 Unresolved table name `$index`@`select#1` for NO_ICP hint
11511151
CREATE TABLE ` quoted name test` (i INT);
11521152
SELECT /*+ BKA(` quoted name test`) */ 1 FROM t1;
11531153
1
@@ -1184,7 +1184,7 @@ SET SQL_MODE = '';
11841184
SELECT /*+ BKA(" quoted name test") */ 1 FROM t1;
11851185
1
11861186
Warnings:
1187-
Warning 1064 Optimizer hint syntax error near '" quoted name test") */ 1 FROM t1' at line 1
1187+
Warning 4204 Unresolved table name `" quoted name test"`@`select#1` for BKA hint
11881188
DROP TABLE ` quoted name test`;
11891189
DROP TABLE `test1``test2```;
11901190
# Valid hints, no warning:
@@ -1228,11 +1228,11 @@ CREATE TABLE tableТ (i INT);
12281228
SELECT /*+ BKA(tableТ) */ 1 FROM t1;
12291229
1
12301230
Warnings:
1231-
Warning 4199 Unresolved name `tableТ`@`select#1` for BKA hint
1231+
Warning 4204 Unresolved table name `tableТ`@`select#1` for BKA hint
12321232
SELECT /*+ BKA(test@tableТ) */ 1 FROM t1;
12331233
1
12341234
Warnings:
1235-
Warning 4198 Query block name `tableТ` is not found for BKA hint
1235+
Warning 4203 Query block name `tableТ` is not found for BKA hint
12361236
DROP TABLE tableТ;
12371237
CREATE TABLE таблица (i INT);
12381238
SELECT /*+ BKA(`таблица`) */ 1 FROM t1;
@@ -1242,11 +1242,11 @@ Warning 4199 Unresolved name `таблица`@`select#1` for BKA hint
12421242
SELECT /*+ BKA(таблица) */ 1 FROM t1;
12431243
1
12441244
Warnings:
1245-
Warning 4199 Unresolved name `таблица`@`select#1` for BKA hint
1245+
Warning 4204 Unresolved table name `таблица`@`select#1` for BKA hint
12461246
SELECT /*+ BKA(test@таблица) */ 1 FROM t1;
12471247
1
12481248
Warnings:
1249-
Warning 4198 Query block name `таблица` is not found for BKA hint
1249+
Warning 4203 Query block name `таблица` is not found for BKA hint
12501250
SELECT /*+ NO_ICP(`\D1`) */ 1 FROM t1;
12511251
1
12521252
Warnings:
@@ -1287,12 +1287,12 @@ SELECT /*+ NO_ICP(10) */ 1;
12871287
1
12881288
1
12891289
Warnings:
1290-
Warning 1064 Optimizer hint syntax error near '10) */ 1' at line 1
1290+
Warning 4204 Unresolved table name `10`@`select#1` for NO_ICP hint
12911291
SELECT /*+ NO_ICP( */ 1;
12921292
1
12931293
1
12941294
Warnings:
1295-
Warning 1064 Optimizer hint syntax error near '*/' at line 1
1295+
Warning 1064 Optimizer hint syntax error near '*/ 1' at line 1
12961296
SELECT /*+ NO_ICP) */ 1;
12971297
1
12981298
1
@@ -1302,7 +1302,7 @@ SELECT /*+ NO_ICP(t1 */ 1;
13021302
1
13031303
1
13041304
Warnings:
1305-
Warning 1064 Optimizer hint syntax error near '*/' at line 1
1305+
Warning 1064 Optimizer hint syntax error near '*/ 1' at line 1
13061306
SELECT /*+ NO_ICP(t1 ( */ 1;
13071307
1
13081308
1
@@ -1347,7 +1347,7 @@ NO_ICP(@qb ident)
13471347
1
13481348
1
13491349
Warnings:
1350-
Warning 4198 Query block name `qb` is not found for NO_ICP hint
1350+
Warning 4203 Query block name `qb` is not found for NO_ICP hint
13511351
SELECT /*+
13521352
? bad syntax
13531353
*/ 1;

sql/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ SET (SQL_SOURCE
194194
opt_vcol_substitution.h
195195
opt_vcol_substitution.cc
196196
opt_hints_parser.cc opt_hints_parser.h scan_char.h
197+
opt_hints.cc opt_hints.h
197198
${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
198199
${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
199200
${GEN_SOURCES}

sql/mem_root_array.h

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
__has_trivial_destructor is supported by some (but not all)
4444
compilers we use.
4545
*/
46+
4647
template<typename Element_type, bool has_trivial_destructor>
4748
class Mem_root_array
4849
{
@@ -53,7 +54,6 @@ class Mem_root_array
5354
Mem_root_array(MEM_ROOT *root)
5455
: m_root(root), m_array(NULL), m_size(0), m_capacity(0)
5556
{
56-
DBUG_ASSERT(m_root != NULL);
5757
}
5858

5959
Mem_root_array(MEM_ROOT *root, size_t n, const value_type &val= value_type())
@@ -62,6 +62,20 @@ class Mem_root_array
6262
resize(n, val);
6363
}
6464

65+
Mem_root_array(const Mem_root_array& other)
66+
{
67+
do_copy_construct(other);
68+
}
69+
70+
Mem_root_array &operator=(const Mem_root_array& other)
71+
{
72+
if(this != &other)
73+
{
74+
clear();
75+
do_copy_construct(other);
76+
}
77+
}
78+
6579
~Mem_root_array()
6680
{
6781
clear();
@@ -231,14 +245,22 @@ class Mem_root_array
231245
const MEM_ROOT *mem_root() const { return m_root; }
232246

233247
private:
234-
MEM_ROOT *const m_root;
235-
Element_type *m_array;
236-
size_t m_size;
237-
size_t m_capacity;
238-
239-
// Not (yet) implemented.
240-
Mem_root_array(const Mem_root_array&);
241-
Mem_root_array &operator=(const Mem_root_array&);
248+
MEM_ROOT *m_root;
249+
Element_type *m_array= nullptr;
250+
size_t m_size= 0;
251+
size_t m_capacity= 0;
252+
253+
void do_copy_construct(const Mem_root_array& other)
254+
{
255+
m_root= other.m_root;
256+
reserve(other.size());
257+
for (size_t ix= 0; ix < other.size(); ++ix)
258+
{
259+
Element_type *p= &m_array[ix];
260+
new (p) Element_type(other[ix]);
261+
}
262+
m_size= other.m_size;
263+
}
242264
};
243265

244266

sql/multi_range_read.cc

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "sql_statistics.h"
2222
#include "rowid_filter.h"
2323
#include "optimizer_defaults.h"
24+
#include "opt_hints.h"
2425

2526
static void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
2627
Cost_estimate *cost);
@@ -1148,7 +1149,9 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
11481149
buf_manager.reset_buffer_sizes= do_nothing;
11491150
buf_manager.redistribute_buffer_space= do_nothing;
11501151

1151-
if (mode & (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))
1152+
if (!hint_key_state(thd, table, h_arg->active_index,
1153+
MRR_HINT_ENUM, OPTIMIZER_SWITCH_MRR) ||
1154+
mode & (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))
11521155
goto use_default_impl;
11531156

11541157
/*
@@ -1901,10 +1904,16 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
19011904
THD *thd= primary_file->get_table()->in_use;
19021905
TABLE_SHARE *share= primary_file->get_table_share();
19031906

1907+
const bool mrr_on= hint_key_state(thd, table, keyno, MRR_HINT_ENUM,
1908+
OPTIMIZER_SWITCH_MRR);
1909+
const bool force_dsmrr_by_hints=
1910+
hint_key_state(thd, table, keyno, MRR_HINT_ENUM, 0) ||
1911+
hint_table_state(thd, table, BKA_HINT_ENUM, 0);
1912+
19041913
bool doing_cpk_scan= check_cpk_scan(thd, share, keyno, *flags);
19051914
bool using_cpk= primary_file->is_clustering_key(keyno);
19061915
*flags &= ~HA_MRR_IMPLEMENTATION_FLAGS;
1907-
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_MRR) ||
1916+
if (!(mrr_on || force_dsmrr_by_hints) ||
19081917
*flags & HA_MRR_INDEX_ONLY ||
19091918
(using_cpk && !doing_cpk_scan) || key_uses_partial_cols(share, keyno))
19101919
{
@@ -1919,15 +1928,17 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
19191928
&dsmrr_cost))
19201929
return TRUE;
19211930

1922-
bool force_dsmrr;
19231931
/*
19241932
If mrr_cost_based flag is not set, then set cost of DS-MRR to be minimum of
19251933
DS-MRR and Default implementations cost. This allows one to force use of
19261934
DS-MRR whenever it is applicable without affecting other cost-based
1927-
choices.
1935+
choices. Note that if MRR or BKA hint is
1936+
specified, DS-MRR will be used regardless of cost.
19281937
*/
1929-
if ((force_dsmrr= !optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_COST_BASED)) &&
1930-
dsmrr_cost.total_cost() > cost->total_cost())
1938+
const bool force_dsmrr=
1939+
(force_dsmrr_by_hints ||
1940+
!optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_COST_BASED));
1941+
if (force_dsmrr && dsmrr_cost.total_cost() > cost->total_cost())
19311942
dsmrr_cost= *cost;
19321943

19331944
if (force_dsmrr || dsmrr_cost.total_cost() <= cost->total_cost())

0 commit comments

Comments
 (0)