【MySQL】性能优化之 straight_join

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:
   研究过或者熟悉oracle性能调优的朋友都知道oracle 提供很多hint 指定from 后的表的连接顺序,如use_hash  ordered ,leading 等,而MySQL 对表的连接只支持 nested loop Join, 提供的表连接驱动的hint 只有--straight_join(相当于Oracle里面的use_nl).其语法如下:
  select ..from  tab1  straiht_join  tab2 where ...
straight_join 实际上与内连接 inner join 表现完全一致,不同的是使用了 straight_join 后,tab1 会先于 tab2 载入。
   MySQL 在执行 inner join 的时候,会根据自己内部的优化规则来决定先载入 tab1 还是 tab2,如果您确认 MySQL 载入表的顺序并不是最优化的时候,就可以使用 straight_join 以替代 inner join,来强制MySQL 选择指定的执行顺序。
【现象】
生产环境中遇到一个例子,执行sql需要1.29s 已经超出业务方的要求,需要进行优化,sql 如下

select  d.instance_no,d.zone_id, d.region_no,d.user_id,d.cores,d.mem,d.disk, d.tx_pub , u.idkp , m.image_no, m.platform, m.image_size
from  user u, instance d , image m
where d.region_no = 'cn-cm9002' and
       u.user_id = d.user_id and
       d.image_id = m.image_id and
       d.status != 8 and 
       d.gmt_create <'2013-08-19 14:00:00';
22664653_201309080333261.jpg

hy@3309 03:09:09>explain select  d.instance_no,d.zone_id, d.region_no,d.user_id,d.cores,d.mem,d.disk, d.tx_pub , u.idkp , m.image_no, m.platform, m.image_size
    -> from  user u, instance d , image m
    -> where d.region_no = 'cn-cm9002' and
    ->        u.user_id = d.user_id and
    ->        d.image_id = m.image_id and
    ->        d.status != 8 and 
    ->        d.gmt_create <'2013-08-19 14:00:00';
+----+-------------+-------+--------+-------------------------------------+--------------------+---------+------------------+--------+-------------+
| id | select_type | table | type   | possible_keys                       | key                | key_len | ref              | rows   | Extra       |
+----+-------------+-------+--------+-------------------------------------+--------------------+---------+------------------+--------+-------------+
|  1 | SIMPLE      | u     | index  | PRIMARY                             | idkp        | 98      | NULL             | 133002 | Using index |
|  1 | SIMPLE      | d     | ref    | image_id,ind_i_uid_hostname,user_id | ind_i_uid_hostname | 4       | hy.u.user_id  |      1 | Using where |
|  1 | SIMPLE      | m     | eq_ref | PRIMARY                             | PRIMARY            | 4       | hy.d.image_id |      1 |             |
+----+-------------+-------+--------+-------------------------------------+--------------------+---------+------------------+--------+-------------+
3 rows in set (0.00 sec)

【解决方法】
使用 straight_join 方式优化sql 执行的顺序 结果如下:
rac1@3309 15:01:55>explain select  d.instance_no,d.zone_id, d.region_no,d.user_id,d.cores,d.mem,d.disk, d.tx_pub , u.idkp , m.image_no, m.platform, m.image_size
    ->       from instance d straight_join  user u on u.user_id = d.user_id,  image m
    ->       where d.region_no = 'cn-cm9002' and
    ->             d.image_id = m.image_id and
    ->             d.status != 8 and 
    ->             d.gmt_create <'2013-08-19 14:00:00';
+----+-------------+-------+--------+-------------------------------------+---------+---------+------------------+--------+-------------+
| id | select_type | table | type   | possible_keys                       | key     | key_len | ref              | rows   | Extra       |
+----+-------------+-------+--------+-------------------------------------+---------+---------+------------------+--------+-------------+
|  1 | SIMPLE      | d     | ALL    | image_id,ind_i_uid_hostname,user_id | NULL    | NULL    | NULL             | 316473 | Using where |
|  1 | SIMPLE      | m    | eq_ref | PRIMARY                             | PRIMARY | 4       | hy.d.image_id |      1 |             |
|  1 | SIMPLE      | u     | eq_ref | PRIMARY                             | PRIMARY | 4       | hy.d.user_id  |      1 |             |
+----+-------------+-------+--------+-------------------------------------+---------+---------+------------------+--------+-------------+
3 rows in set (0.00 sec)

新的sql执行结果:
  22664653_201309080333311.jpg

【问题分析】
上面的介绍中描述mysql的优化器只支持 nest loop ,对于多表连接会mysql优化器采用了简单的方式:选择结果集小的表作为驱动表。
instance表连接 user表有两种连接方式:
A 选择user 表作为驱动表 优化器扫描133002行
B 选择instance表作为驱动表 优化器扫描  316473行

因此 优化器选择了看起来正确的执行计划 以user表作为驱动表。但是 我们查看where条件,正确的应该是 通过instance 的region_no,status ,gmt_create 过滤得到instance的结果集,再来和user,image中的表进行关联。
而执行计划是扫描user表中全部的记录再去关联instance 表和image表,显然执行顺序有 偏差。因此加上straight_join hint 之后,强制优化器选择 instance为驱动表,按照正确的执行计划执行。
 
附上表的记录数:
hy@3309 01:11:17> select count(*) from user;
+----------+
| count(*) |
+----------+
|   134221 |
+----------+
1 row in set (0.02 sec)

hy@3309 01:19:44> select count(*) from instance;
+----------+
| count(*) |
+----------+
|   375732 |
+----------+
1 row in set (0.06 sec)

hy@3309 01:19:54> select count(*) from image;   
+----------+
| count(*) |
+----------+
|    18858 |
+----------+
1 row in set (0.00 sec)
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
存储 关系型数据库 MySQL
《MySQL 简易速速上手小册》第3章:性能优化策略(2024 最新版)
《MySQL 简易速速上手小册》第3章:性能优化策略(2024 最新版)
47 2
|
17天前
|
存储 缓存 关系型数据库
16. mysql的性能优化
优化MySQL性能主要从设计、功能和架构三方面入手。选择适合的存储引擎(如MyIsam用于高读写,InnoDB处理事务),选取恰当的字段类型(如使用char for定长字符串,tinyint for有限状态),并遵循数据库范式设计。功能上,利用索引优化查询,使用缓存减少数据库负担,并进行分库分表。在架构上,实施主从复制、读写分离和负载均衡来提升性能。
20 0
|
17天前
|
存储 监控 关系型数据库
轻松入门Mysql:MySQL性能优化与监控,解锁进销存系统的潜力(23)
轻松入门Mysql:MySQL性能优化与监控,解锁进销存系统的潜力(23)
|
17天前
|
存储 SQL 关系型数据库
MySQL性能优化
MySQL性能优化
18 0
|
17天前
|
SQL 缓存 关系型数据库
mysql性能优化-慢查询分析、优化索引和配置
mysql性能优化-慢查询分析、优化索引和配置
121 1
|
17天前
|
SQL 关系型数据库 MySQL
轻松入门MySQL:深入学习数据库表管理,创建、修改、约束、建议与性能优化(3)
轻松入门MySQL:深入学习数据库表管理,创建、修改、约束、建议与性能优化(3)
|
9天前
|
SQL 关系型数据库 数据库
阿里云数据库 RDS SQL Server版实战【性能优化实践、优点探析】
本文探讨了Amazon RDS SQL Server版在云数据库中的优势,包括高可用性、可扩展性、管理便捷、安全性和成本效益。通过多可用区部署和自动备份,RDS确保数据安全和持久性,并支持自动扩展以适应流量波动。可视化管理界面简化了监控和操作,而数据加密和访问控制等功能保障了安全性。此外,弹性计费模式降低了运维成本。实战应用显示,RDS SQL Server版能有效助力企业在促销高峰期稳定系统并保障数据安全。阿里云的RDS SQL Server版还提供了弹性伸缩、自动备份恢复、安全性和高可用性功能,进一步优化性能和成本控制,并与AWS生态系统无缝集成,支持多种开发语言和框架。
49 2
|
17天前
|
缓存 关系型数据库 MySQL
MySQL数据库性能优化实战
【4月更文挑战第30天】本文探讨了MySQL性能优化实战技巧,包括硬件与配置优化(如使用SSD、增加内存和调整配置参数)、索引优化(创建合适索引、使用复合索引及定期维护)、查询优化(避免全表扫描、减少JOIN和使用LIMIT)、分区与分片(表分区和数据库分片),以及使用缓存、定期清理数据库和监控诊断。通过这些方法,可以提升数据库性能和响应速度。
|
17天前
|
缓存 关系型数据库 MySQL
【专栏】提升MySQL性能和高可用性的策略,包括索引优化、查询优化和事务管理
【4月更文挑战第27天】本文探讨了提升MySQL性能和高可用性的策略,包括索引优化、查询优化和事务管理。通过合理使用B-Tree和哈希索引,避免过度索引,以及优化查询语句和利用查询缓存,可以改善性能。事务管理中,应减小事务大小并及时提交,以保持系统效率。主从或双主复制可增强高可用性。综合运用这些方法,并根据实际需求调整,是优化MySQL的关键。
|
17天前
|
SQL Oracle 关系型数据库
Mysql性能优化这5点你知道吗?简单却容易被初学者忽略!
在日常工作中,我们常用的数据库无非是Mysql、Oracle、SqlServer、DB2这几种(仅针对关系型数据库中),对于我们来说,数据库的性能优化是一个重点问题,也是很多公司面试时喜欢提及的,这里总结了一些比较常见,但又相对容易忽略的部分,供大家批判学习。
20 2