MySQL8.0 优化器介绍(四)

  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者: 奥特曼爱小怪兽
  • 文章来源:GreatSQL社区原创

往期回顾

MySQL8.0 优化器介绍(一)

MySQL8.0 优化器介绍(二)

MySQL8.0 优化器介绍(三)

MySQL8.0在优化器上做了很多努力和优化,仍然不足以保证每条sql,都能拥有合理的执行计划,有些情况需要通过hint来干预。MySQL8.0在hint的种类上进行了新增。本篇主要讲我们可以有哪些方法影响优化器。

优化器配置 Configuring the Optimizer

有很多方法影响优化器。

configuration options

mysql.engine_cost , mysql.server_cost 具体表字段的含义,怎么配置,配置后怎么生效的细节见官网。需要注意的是,配置完以上表后,得做一个FLUSH OPTIMIZER_COSTS; 的动作。

另外还有两个重要参数 optimizer_prune_level 、optimizer_search_depth 值得注意。

Optimizer Switches

optimizer switches 是一个复合的option 集。8.0.25 默认的optimizer switches

mysql> show  variables  like '%swi%' \G
*************************** 1. row ***************************
Variable_name: optimizer_switch
        Value: 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,
               se_index_extensions=on,condition_fanout_filter=on,
               derived_merge=on,use_invisible_indexes=off,skip_scan=on,
               hash_join=on,subquery_to_derived=off,prefer_ordering_index=on,
               hypergraph_optimizer=off,derived_condition_pushdown=on
1 row in set (0.00 sec)

optimizer switches 尽管可以会话级设置,但大多数情况下,我们都当作一个全局参数在用。

特别是5.7升级8.0,8.0小版本升级的时候,optimizer switches的检查必须作为一个单独项。前面的文章中已经介绍了10多种优化器的策略、算法。更多细节参考(https://dev.mysql.com/doc/refman/8.0/en/switchable-optimizations.html

Optimizer Hints

https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html

Optimizer Hints的特性是5.7引入的,并在8.0做了扩展。可以通过hint 来影响查询计划的执行。

Hint 比optimizer switches的选项控制更精细,可以做到query block,table,index 三级。并且支持在查询期间更改配置选项的值,比会话级修改参数更细。比如可以限制一个sql的执行时间:

SELECT /*+ MAX_EXECUTION_TIME(2000) */
 id, Name, District
 FROM world.city
 WHERE CountryCode = 'AUS';
 ##查询被限制在2s之内。

Table 8.2 Optimizer Hints Available

图片

  • Global: The hint applies to the whole query.
  • Query Block: The hint applies to a group of joins. For example, the top level of the query is a query block; a subquery is another query block. Hints that apply to a query block can in some cases also take the table names for a join to limit the hint to a specific join.
  • Table: The hint applies to a specific table.
  • Index: The hint applies to the use of a specific index.

hint的语法 /*+ ... */ 注意三个点的前后都有一个空格。语法树都比较好看,举例几个比较难懂的语法。

#QB_NAME() 的用法。
可以把一个复杂的查询,划分成多个 query_block,然后再针对每个 qb进行hint的调优

#定义一个qb
SELECT /*+ QB_NAME(payment) */
 rental_id
 FROM sakila.payment
 WHERE staff_id = 1 AND customer_id = 75;

#复杂查询中,对一个qb进行hint
 SELECT /*+ NO_INDEX_MERGE(@payment payment) */
       rental_id, 
       rental_date,
       return_date
  FROM sakila.rental
 WHERE rental_id IN (
                     SELECT /*+ QB_NAME(payment) */
                            rental_id
                       FROM sakila.payment
                      WHERE staff_id = 1 AND customer_id = 75);

SELECT /*+ NO_INDEX_MERGE(payment@payment) */
       rental_id, 
       rental_date,
       return_date
  FROM sakila.rental
 WHERE rental_id IN (
                     SELECT /*+ QB_NAME(payment) */
                            rental_id
                       FROM sakila.payment
                      WHERE staff_id = 1 AND customer_id = 75);
#查询期间更改配置选项的值
SELECT /*+ SET_VAR(join_buffer_size = 1048576)
           SET_VAR(optimizer_search_depth = 0) */
       CountryCode, 
       country.Name AS Country,
       city.Name AS City, 
       city.District
  FROM world.country IGNORE INDEX (Primary)
 INNER JOIN world.city IGNORE INDEX (CountryCode)
         ON city.CountryCode = country.Code
      WHERE Continent = 'Asia';

 #SET_VAR一次只能修改一个vairable,多个vairable 需要多个SET_VAR
 #SET_VAR 不支持表达式,=号右边必须是具体的值

ps:怎么练习 sql 级别的hint的使用?

  1. 多读几遍25种hint的描述。
  2. 拿着一个正常的执行计划做参考,把一个异常的执行计划试着用hint改到期望的计划。
  3. 大多数的hint都是成对出现的,有关,有开两种组合。把一个正常的计划,试着用hint把计划改得糟糕。
  4. 从简单的sql,单表的入手。逐渐过渡到多表,单机,分布式数据库
  5. google MySQL hints 的经验 并实践。

Index Hints

这个大家应该很熟悉,ignore、use、force index

SELECT ci.CountryCode, 
       co.Name AS Country,
       ci.Name AS City, 
       ci.District
  FROM world.country co IGNORE INDEX (Primary)
 INNER JOIN world.city ci IGNORE INDEX (CountryCode)
    ON ci.CountryCode = co.Code
 WHERE co.Continent = 'Asia';

 SELECT *
   FROM world.city USE INDEX FOR ORDER BY (Primary)
  WHERE CountryCode = 'AUS'
  ORDER BY ID;

资源组(Resource Groups)

https://dev.mysql.com/doc/refman/8.0/en/resource-groups.html#resource-group-restrictions

对于high-concurrency systems的场景,MySQL8.0 在server 层,提供了一个resource groups 特性。

select  *  from  information_schema.RESOURCE_GROUPS \G
*************************** 1. row ***************************
   RESOURCE_GROUP_NAME: USR_default
   RESOURCE_GROUP_TYPE: USER
RESOURCE_GROUP_ENABLED: 1
              VCPU_IDS: 0x302D35
       THREAD_PRIORITY: 0
*************************** 2. row ***************************
   RESOURCE_GROUP_NAME: SYS_default
   RESOURCE_GROUP_TYPE: SYSTEM
RESOURCE_GROUP_ENABLED: 1
              VCPU_IDS: 0x302D35
       THREAD_PRIORITY: 0
2 rows in set (0.00 sec)

CREATE RESOURCE GROUP my_group  
TYPE = USER  
VCPU = 2-3,6,7 
THREAD_PRIORITY = 0 
ENABLE;

##RESOURCE_GROUP 是影响线程级别的,需要安装商业版本的thread_pool 
##(http://www.tdpub.cn/Blog/detail/id/1007.html)  thread_pool相关介绍 

##(https://zhuanlan.zhihu.com/p/114149600)  
##MySQL源码级线程init过程的分析 高并发创建MySQL线程时,遇到瓶颈,可能用得到。注意MySQL可以允许2000个并发同时运行与MySQL 1秒内创建200个并发 是不一样的概念。前者类似于高速上的车,后者类似于高速的入口。
##另外创建会话(连接)时的init 与show  processlist 看到State='init' 不一样。
##后面我的同事会投一篇<从processlist.state分析SQL执行阶段>的文章出来介绍。

##(https://zhuanlan.zhihu.com/p/114343815)   MySQL源码级连接与线程管理

 SELECT THREAD_ID, RESOURCE_GROUP  FROM performance_schema.threads  limit 5;
+-----------+----------------+
| THREAD_ID | RESOURCE_GROUP |
+-----------+----------------+
|         1 | SYS_default    |
|         3 | SYS_default    |
|         4 | SYS_default    |
|         5 | SYS_default    |
|         6 | SYS_default    |
+-----------+----------------+

资源组可用于指定线程允许使用哪些CPU,以及线程应使用哪个优先级执行。
这对于确定某些线程的优先级非常有用
执行优先级高于其他线程或防止资源争用。

本系列文章一共4篇,概括地介绍了优化器是怎么工作的,join的优化算法,以及优化 join的方法;以及怎么配置optimizer。

MySQL使用基于成本的优化器,其中估计查询执行的每个部分的成本,并选择总体查询计划以最小化成本。作为优化的一部分,优化器将使用各种转换重写查询,找到最佳连接顺序,并做出其他决定,例如应使用哪些索引。

MySQL 已经有三种基本的join 算法: NL,BNL,HASH JOIN 。HASH JOIN 弥补了NL 在缺少索引,或者索引选择性不佳时,触发的性能问题。同时HASH JOIN 也带来自身的一些性能问题。

重点聚焦了三种join 优化,index_merge 可以使用多个索引来提高效率。MRR 是通过减少随机IO 来提高效率。BKA=BNL+MRR

另外还介绍了多种影响优化器的方法。

一些有意思的链接:

http://www.unofficialmysqlguide.com/index.html)(https://www.percona.com/blog/count-vs-countcol-in-mysql/)

Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html

社区2022年度勋章获奖名单: https://greatsql.cn/thread-184-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

技术交流:

image-20221030163217640

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 8.0的性能优化可以通过合理安排资源和调整系统参数来实现。其中,优化服务硬件和优化MySQL服务参数是两个主要方面。优化服务硬件包括选择适当的硬件设备,如处理、内存和磁盘,以满足数据库的需求。对于可以制定参数的操作系统,还可以针对MySQL进行操作系统优化。 而优化MySQL服务参数则包括调整MySQL的配置参数,以提高查询速度和节省资源。这可以包括调整innodb_buffer_pool_size参数,该参数决定了InnoDB存储引擎在内存中缓存数据和索引的大小,从而影响性能。可以通过合理设置该参数的值,来提高系统的性能。 总之,MySQL 8.0的性能优化可以通过优化服务硬件和调整MySQL服务参数两个方面来实现,以提高查询速度、节省资源并使MySQL运行更快。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [mysql8.0 性能优化配置 innodb_buffer_pool_size](https://blog.csdn.net/haveqing/article/details/130358261)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [MySQL8.0 性能优化](https://blog.csdn.net/S_zhangmin/article/details/123142506)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值