optimizer hints
In version MySQL 5.7.7 Oracle presented a new promising feature: optimizer hints. However it did not publish any documentation about the hints. The only note which I found in the user manual about the hints is:
- It is now possible to provide hints to the optimizer by including
/*+ ... */comments following theSELECT,INSERT,REPLACE,UPDATE, orDELETEkeyword of SQL statements. Such statements can also be used withEXPLAIN. Examples:SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1
FROM t3 WHERE f1 > 30 AND f1 < 33;
SELECT /*+ BKA(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...;
SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...;
There are also three worklogs: WL #3996, WL #8016 and WL #8017. But they describe the general concept and do not have much information about which optimizations can be used and how. More light on this provided by slide 59 from Øystein Grøvlen’s session at Percona Live. But that’s all: no “official” full list of possible optimizations, no use cases… nothing.
I tried to sort it out myself.
My first finding is the fact that slide #59 really lists six of seven possible index hints. Confirmation for this exists in one of two new files under sql directory of MySQL source tree, created for this new feature.
$cat sql/opt_hints.h
...
/**
Hint types, MAX_HINT_ENUM should be always last.
This enum should be synchronized with opt_hint_info
array(see opt_hints.cc).
*/
enum opt_hints_enum
{
BKA_HINT_ENUM= 0,
BNL_HINT_ENUM,
ICP_HINT_ENUM,
MRR_HINT_ENUM,
NO_RANGE_HINT_ENUM,
MAX_EXEC_TIME_HINT_ENUM,
QB_NAME_HINT_ENUM,
MAX_HINT_ENUM
};
Looking into file sql/opt_hints.cc we can find out what these optimizations give not much choice: either enable or disable.
$cat sql/opt_hints.cc
...
struct st_opt_hint_info opt_hint_info[]=
{
{"BKA", true, true},
{"BNL", true, true},
{"ICP", true, true},
{"MRR", true, true},
{"NO_RANGE_OPTIMIZATION", true, true},
{"MAX_EXECUTION_TIME", false, false},
{"QB_NAME", false, false},
{0, 0, 0}
};
A choice for the way to include hints into SQL statements: inside comments with sign “+”
/*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */
, – is compatible with style of optimizer hints which Oracle uses.
We actually had access to these hints before: they were accessible via variable optimizer_switch. At least such optimizations like BKA, BNL, ICP, MRR. But with new syntax we cannot only modify this access globally or per session, but can turn on or off particular optimization for a single table and column in the query. I can demonstrate it on this quite artificial but always accessible example:
mysql> use mysql
Database changed
mysql> explain select * from user where host in ('%', '127.0.0.1');
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | user | NULL | range | PRIMARY | PRIMARY | 180 | NULL | 2 | 100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.01 sec)
mysql> explain select /*+ NO_RANGE_OPTIMIZATION(user PRIMARY) */ * from user where host in ('%', '127.0.0.1');
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | user | NULL | ALL | PRIMARY | NULL | NULL | NULL | 5 | 40.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
I used one more hint, which we could not turn on or off directly earlier: range optimization.
One more “intuitively” documented feature is the ability to turn on or off a particular optimization. This works only for BKA, BNL, ICP and MRR: you can specify NO_BKA(table[[, table]…]), NO_BNL(table[[, table]…]), NO_ICP(table indexes[[, table indexes]…]) and NO_MRR(table indexes[[, table indexes]…]) to avoid using these algorithms for particular table or index in the JOIN.
MAX_EXECUTION_TIME does not require any table or key name inside. Instead you need to specify maximum time in milliseconds which query should run:
mysql> select /*+ MAX_EXECUTION_TIME(1000) */ sleep(1) from user;
ERROR 3024 (HY000): Query execution was interrupted, max_statement_time exceeded
mysql> select /*+ MAX_EXECUTION_TIME(10000) */ sleep(1) from user;
+----------+
| sleep(1) |
+----------+
| 0 |
| 0 |
| 0 |
| 0 |
| 0 |
+----------+
5 rows in set (5.00 sec)
QB_NAME is more complicated. WL #8017 tells us this is custom context. But what is this? The answer is in the MySQL test suite! Tests for optimizer hints exist in file t/opt_hints.test For QB_NAME very first entry is query:
EXPLAIN SELECT /*+ NO_ICP(t3@qb1 f3_idx) */ f2 FROM
(SELECT /*+ QB_NAME(QB1) */ f2, f3, f1 FROM t3 WHERE f1 > 2 AND f3 = 'poiu') AS TD
WHERE TD.f1 > 2 AND TD.f3 = 'poiu';
So we can specify custom QB_NAME for any subquery and specify optimizer hint only for this context.
To conclude this quick overview I want to show a practical example of when query hints are really needed. Last week I worked on an issue where a customer upgraded from MySQL version 5.5 to 5.6 and found some of their queries started to work slower than before. I wrote an answer which could sound funny, but still remains correct: “One of the reasons for such behavior is optimizer improvements. While they all are made for better performance, some queries – optimized for older versions – can start working slower than before.”
To demonstrate a public example of such a query I will use my favorite source of information: MySQL Community Bugs Database. In a search for Optimizer regression bugs that are still not fixed we can find bug #68919 demonstrating regression in case the MRR algorithm is used for queries with LIMIT. In run queries, shown in the bug report, we will see a huge difference:
mysql> SELECT * FROM t1 WHERE i1>=42 AND i2<=42 LIMIT 1;
+----+----+----+----+
| pk | i1 | i2 | i3 |
+----+----+----+----+
| 42 | 42 | 42 | 42 |
+----+----+----+----+
1 row in set (6.88 sec)
mysql> explain SELECT * FROM t1 WHERE i1>=42 AND i2<=42 LIMIT 1;
+----+-------------+-------+------------+-------+---------------+------+---------+------+---------+----------+----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+---------+----------+----------------------------------+
| 1 | SIMPLE | t1 | NULL | range | idx | idx | 4 | NULL | 9999958 | 33.33 | Using index condition; Using MRR |
+----+-------------+-------+------------+-------+---------------+------+---------+------+---------+----------+----------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SELECT /*+ NO_MRR(t1) */ * FROM t1 WHERE i1>=42 AND i2<=42 LIMIT 1;
+----+----+----+----+
| pk | i1 | i2 | i3 |
+----+----+----+----+
| 42 | 42 | 42 | 42 |
+----+----+----+----+
1 row in set (0.00 sec)
With MRR query execution takes 6.88 seconds and 0 if MRR is not used! But the bug report itself suggests using
optimizer_switch="mrr=off";
as a workaround. And this will work perfectly well if you are OK to run
SET optimizer_switch="mrr=off";
every time you are running a query which will take advantage of having it OFF. With optimizer hints you can have one or another algorithm to be ON for particular table in the query and OFF for another one. I, again, took quite an artificial example, but it demonstrates the method:
mysql> explain select /*+ MRR(dept_emp) */ * from dept_emp where to_date in  (select /*+ NO_MRR(salaries)*/ to_date from salaries where salary >40000 and salary <45000) and emp_no >10100 and emp_no < 30200 and dept_no in ('d005', 'd006','d007');
+----+--------------+-------------+------------+--------+------------------------+------------+---------+----------------------------+---------+----------+-----------------------------------------------+
| id | select_type  | table       | partitions | type   | possible_keys          | key        | key_len | ref                        | rows    | filtered | Extra                                         |
+----+--------------+-------------+------------+--------+------------------------+------------+---------+----------------------------+---------+----------+-----------------------------------------------+
|  1 | SIMPLE       | dept_emp    | NULL       | range  | PRIMARY,emp_no,dept_no | dept_no    | 8       | NULL                       |   10578 |   100.00 | Using index condition; Using where; Using MRR |
|  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_key>             | <auto_key> | 3       | employees.dept_emp.to_date |       1 |   100.00 | NULL                                          |
|  2 | MATERIALIZED | salaries    | NULL       | ALL    | salary                 | NULL       | NULL    | NULL                       | 2838533 |    17.88 | Using where                                   |
+----+--------------+-------------+------------+--------+------------------------+------------+---------+----------------------------+---------+----------+-----------------------------------------------+
3 rows in set, 1 warning (0.00 sec)
The post Optimizer hints in MySQL 5.7.7 – The missed manual appeared first on MySQL Performance Blog.
optimizer hints的更多相关文章
- 19 Using Optimizer Hints
		19.1 Overview of Optimizer Hints A hint is an instruction to the optimizer. In a test or development ... 
- MYSQL COST optimizer
		http://blog.chinaunix.net/uid-26896862-id-3326400.html https://www.slideshare.net/olavsa/mysql-optim ... 
- rule-based optimizer  cost-based optimizer
		SQL processing uses the following main components to execute a SQL query: The Parser checks both syn ... 
- 使用Ado.net执行SP很慢,而用SSMS执行很快
		今天遇到一个问题,有用户反应,在site上打开报表,一直loading,出不来结果. 遇到这种问题,我立刻simulate用户使用Filter Condition,问题repro,看来不是偶然事件,通 ... 
- Peeking into Apache Flink's Engine Room
		http://flink.apache.org/news/2015/03/13/peeking-into-Apache-Flinks-Engine-Room.html Join Processin ... 
- SET Statements for SQLServer
		SET SHOWPLAN_ALL { ON | OFF } It will not execute the TSQL statements. It cannot be specified inside ... 
- DBMS_STATS.GATHER_TABLE_STATS
		由于Oracle的优化器是CBO,所以对象的统计数据对执行计划的生成至关重要! 作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息(默认参数下是对表进行直方图信 ... 
- SQL Server 锁详解
		锁是一种防止在某对象执行动作的一个进程与已在该对象上执行的其他进行相冲突的机制.也就是说,如果有其他人在操作某个对象,那么你旧不能在该对象上进行操作.你能否执行操作取决于其他用户正在进行的操作. 通过 ... 
- 来,看看MySQL 5.6, 5.7, 8.0的新特性
		对于MySQL的历史,相信很多人早已耳熟能详,这里就不要赘述.下面仅从产品特性的角度梳理其发展过程中的里程碑事件. 1995年,MySQL 1.0发布,仅供内部使用. 1996年,MySQL 3.11 ... 
随机推荐
- C#中获得汉字的首拼音(简化版)
			利用汉字在计算机里面的编码来得到汉字的首拼音: static public string GetChineseSpell(string strText) { int len = strText.Len ... 
- imacros实现Excel数据自动录入到网页中
			一.工具选择 最近接到一个项目,需要将excel数据逐条录入.保存到网页中.经过搜集资料,能实现功能的大概有以下几种方式,按键精灵.autoit.imacros.python+selenium. 按键 ... 
- 【poi】解决java导出excel  海量数据内存溢出问题
			转自百度经验:http://jingyan.baidu.com/article/4853e1e5202c331909f72627.html 那里排版忒恶心,转来这里. 由于项目中有导出海量数据的需求, ... 
- Swift入门系列--Swift官方文档(2.2)--中文翻译--About Swift 关于Swift
			About Swift 关于Swift 官方文档的翻译,仅供参考,本人英语本就不好,边学边翻译,不喜勿喷. Swift is a new programming language for iOS, O ... 
- vim文本编辑器的总结
			说起文本编辑器,在下就不得不说vim这个老古董了,说老吧,但也是老当益壮,至今还是有不少拥护者.的确,vim很实用,在下就先列出vi的优点吧. 1.如果精通了vim,就可以省去鼠标了. 2.vim是跨 ... 
- DragSortListView学习总结
			Drag-sort-listview 是一个支持拖拽排序和左右滑动删除功能的自定义ListView,重写了 TouchInterceptor类来提供更加优美的拖拽动画效果. DSLV主要特性: 完美的 ... 
- RedHat Enterprise Linux 6.4-x86_64 md5:467B53791903F9A0C477CBB1B24FFD1F
			RedHat Enterprise Linux 6.4-x86_64 md5:467B53791903F9A0C477CBB1B24FFD1F 这是下载地址:http://pan.baidu.com/ ... 
- Oracle 搜集统计信息
			常用的统计信息收集脚本: 非分区表: BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', ... 
- Delphi中使用TXMLDocument控件应注意的问题  转
			Delphi中使用TXMLDocument控件应注意的问题 delphiconstructorxmlclass今天写了一个类,其中用到了TXMLDocument控件.这个控件我是要动态生成的. 但是却 ... 
- C++中new和malloc
			1.malloc的工作原理: malloc使用一个数据结构(链表)来维护分配空间链表的构成:分配的空间/上一个空间的数据/下一个空间/空间大小等信息. 对malloc分配的空间不要越界访问,因为 ... 
