前言: 本文目的: 本文结合实际案例讲述MySQL的Comment Syntax(注释语法)中Optimizer Hints(优化器提示)的作用和语法。绝对的干货文章哦! 环境说明: MySQL版本:8.0.20 版权说明: 本文由博主keep丶原创,转载请注明出处。 原文地址: https://blog.csdn.net/qq_38688267/article/details/108375822
控制优化器策略的一种方法是设置 optimizer_switch 1 系统变量,对该变量的更改会影响所有后续查询的执行。
控制优化器的另一种方法是使用优化器提示,该提示可以在单个语句中指定。由于优化程序提示是基于每个语句应用的,因此它们提供了比使用更好的控制语句执行计划 optimizer_switch。例如:你可以在语句中为一个表启用优化,而对另一表禁用优化。语句中的提示优先级高于 optimizer_switch变量的值。
· 重复提示:/*+ MRR(idx1) MRR(idx1) */,MySQL会使用第一个提示并发出有关重复提示的警告。 · 冲突的提示:/*+ MRR(idx1) NO_MRR(idx1) */,MySQL会使用第一个提示并发出有关第二个冲突提示的警告。
提示名称,查询块名称和策略名称不区分大小写。对表和索引名称的引用遵循通常的标识符区分大小写规则全 局: 提示会影响整个语句 查询块: 提示会影响语句中的特定查询块 表 级: 提示会影响查询块中的特定表 索引级: 提示会影响表中的特定索引
MySQL8.0版本中支持的优化器提示如下: 提示名称描述适用范围BKA, NO_BKA影响批量密钥访问联接处理查询块,表BNL, NO_BNLMySQL 8.0.20之前的版本:影响块嵌套循环的连接处理;MySQL 8.0.18及更高版本:还影响哈希联接优化;MySQL 8.0.20及更高版本:仅影响哈希联接优化查询块,表DERIVED_CONDITION_PUSHDOWN, NO_DERIVED_CONDITION_PUSHDOWN对物化派生表使用或忽略派生条件下推优化(在MySQL 8.0.22中添加)查询块,表GROUP_INDEX, NO_GROUP_INDEX在GROUP BY操作中使用或忽略指定的一个或多个索引进行索引扫描 (在MySQL 8.0.20中添加)指数HASH_JOIN, NO_HASH_JOIN影响哈希联接优化(仅适用于MySQL 8.0.18查询块,表INDEX, NO_INDEX充当的组合JOIN_INDEX, GROUP_INDEX以及 ORDER_INDEX,或作为组合 NO_JOIN_INDEX, NO_GROUP_INDEX和 NO_ORDER_INDEX(由在MySQL 8.0.20)指数INDEX_MERGE, NO_INDEX_MERGE影响索引合并优化表,索引JOIN_FIXED_ORDER使用FROM子句中指定的表顺序作为连接顺序查询块JOIN_INDEX, NO_JOIN_INDEX对任何访问方法使用或忽略指定的索引(在MySQL 8.0.20中添加)指数JOIN_ORDER使用提示中指定的表顺序作为连接顺序查询块JOIN_PREFIX将提示中指定的表顺序用于连接顺序的第一张表查询块JOIN_SUFFIX将提示中指定的表顺序用于联接顺序的最后一个表查询块MAX_EXECUTION_TIME限制语句执行时间全局MERGE, NO_MERGE影响派生表/视图合并到外部查询块中表MRR, NO_MRR影响多范围读取优化表,索引NO_ICP影响索引条件下推式优化表,索引NO_RANGE_OPTIMIZATION影响范围优化表,索引ORDER_INDEX, NO_ORDER_INDEX使用或忽略指定的一个或多个索引对行进行排序(在MySQL 8.0.20中添加)指数QB_NAME为查询块分配名称查询块RESOURCE_GROUP在语句执行期间设置资源组全局SEMIJOIN, NO_SEMIJOIN影响半联接策略;从MySQL 8.0.17开始,这也适用于antijoins查询块SKIP_SCAN, NO_SKIP_SCAN影响跳过扫描优化表,索引SET_VAR在语句执行期间设置变量全局SUBQUERY影响物化, IN-to-EXISTS 子查询策略查询块优化器提示的应用场景很多,这里举几个小栗子给大家抛砖引玉。
编码过程中不可避免的会需要编写复杂或大数据量的SQL,这时我们可以提示MySQL给这条SQL分配更多内存以加快执行速度。
-- 给复杂关联查询设置较多关联缓存 SELECT /*+ SET_VAL(join_buffer_size=1024 * 1024 * 2)*/ * FROM t1 LEFT JOIN t2 LEFT JOIN t3 LEFT JOIN t4 ...... -- 增加排序缓存 SELECT /*+ SET_VAR(sort_buffer_size = 16M) */ name FROM people ORDER BY name;
使用optimizer_switch系统变量可以控制优化程序的行为。该变量的值是一组指标,每个指标的值都为on或off指示相应的优化器行为是启用还是禁用。此变量具有全局值和会话值,可以在运行时更改。可以在服务器启动时设置全局默认值。
基本操作如下,详细请阅读官方文档:传送门
-- 查看优化器选项 select @@optimizer_switch; -- 设置优化器选项 set @@optimizer_switch = 'index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=off,skip_scan=on,hash_join=on';
优化器提示的功能非常强大,熟练掌握之后能够让我们的SQL性能得到更进一步的提升。希望这篇文章对大家有所帮助。