MySQL优化 - 性能分析与查询优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

MySQL优化 - 性能分析与查询优化

    优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载选择合理的硬件配置等。

 

1、性能分析

 性能分析包含多方面:CPU、Memory、磁盘/网络IO、MySQL服务器本身等。

1.1 操作系统分析

常规的操作系统分析,在Linux中通常包含一些性能监控命令,如top、vmstat、iostat、strace、iptraf等。

1、内存:内存是大项,高查询消耗大量的查询缓存,内存必须足够,并且给系统本身要预留一些。

2、磁盘:配备高速磁盘+RAID会有更好的读写速度,并且SSD成本逐渐降低,升级成本会在可接受范围。

3、网络:目前市场上千兆万兆网卡已很常见。

4、CPU:虽然很多情况下CPU用不完,但也不能让它成为瓶颈。

生产环境的MySQL多数情况部署在Linux系统中,Linux系统本身可以优化的配置并不多。硬件的选型是复杂,涉及计算机组成的原理性知识,需要额外了解。

 

1.2 MySQL服务性能分析

MySQL服务器的性能通常通过监控命令查看系统工作状态,确定哪些因素成为瓶颈。

1.2.1  SHOW GLOBAL STATUS

显示了目前MySQL的工作状态,包含很多参数,下面对一些参数进行说明,其余的参考官方说明:

====================================

1. Aborted_clients
如果该值随时间增加,检查是否优雅关闭连接,检查max_allowed_packet配置变量是否被超过导致强制中断。

2. Aborted_connections
接近于0,检查网络问题,如果有少量是正常的,比如鉴权失败等。

3. Binlog_cache_disk_use和Binlog_cache_use
大部分事务应该在缓冲中进行,如果disk cache很大,可考虑增加内存缓存。

4. Bytes_recevied和Bytes_sent
如果值很大,检查是否查询超过需要的数据。

5. Com_*
尽量让如Com_rollback这些不常见的变量超过预期,用innotop检查。

6. Create_tmp_tables
优化查询降低该值。

7. Handler_read_rnd_next
Handler_read_rnd_next / Handler_read_rnd显示全表扫面大致平均值,如果很大,只能优化查询。

8. Open_files
不应该接近于open_files_limit,如果接近就应该适当增加open_files_limit。

9. Qcache_*
查询缓存相关。

10. Select_full_join
全联接无索引联接,尽量避免,优化查询。

11. Select_full_range_join
值过高说明使用了范围查询联接表,范围查询比较慢,可优化。

12. Sort_meger_passes
如果值较大可考虑增加sort_buffer_size,查明是那个查询导致使用文件排序。

13. Table_locks_waited
表被锁定导致服务器锁等待,InnoDB的行锁不会使得该变量增加,建议开启慢查询日志。

14. Threads_created
如果值在增加,可考虑增加thread_cache_size。

====================================

 

1.2.2  SHOW ENGINE INNODB STATUS

暂时的数据包含了太多InnoDB核心信息,并且需要比较深的了解InnoDB引擎工作原理,这里不做过多说明,请查阅针对此的专项文档。

注: 通常包含SEMAPHORES、TRANSACTIONS、FILE I/O、LOG、BUFFER POOL AND MEMORY等一些详细值,有些参数是上一次执行以来的平均值,所以建议隔一段时间再打印一次得到这段时间的统计,有点类似iostat的统计磁盘平均读写一样。

 

1.2.3  开启慢查询日志配置

排查导致MySQL运行缓慢的问题SQL,开启慢查询日志配置,可能有很有帮助:

slow_query_log=1
slow_query_log_file=/YOUR_DIR/mysql_slow.log

配合慢查询日志分析工具(如mysqlsla)

 

 

2、查询性能优化

    一般来说在编写SQL时,注意查询是否能使用到索引,是否在大表中或者高频率查询中引起全表扫描,这些主要通过经验分析配合execution plan得到比较理想的查询消耗。

 

2.1 查询基础

了解查询过程,才能知道哪些步骤可能出现瓶颈,execution plan结果也会有所体现,MySQL查询的一般过程:

1. Client往服务器发送查询指令。
2. 服务器查询缓存,如果存在则直接返回,否则下一步。
3. 服务器解析、预处理和优化查询,生成执行计划。
4. 执行引擎调用存储引擎API执行查询。
5. 服务器将结果返回至客户端。

用图表示如下:

 

解析与预处理过程:

- 解析器将查询分解后构造解析树,进行语法解析与验证查询,检查SQL是否有效。

- 预处理器解析语义:如检查表和列是否存在,是否存在歧义等。

- 预处理器检查权限。

查询优化器:

该过程比较复杂,将解析树的结果变成执行计划,优化器的任务是寻找最好的方式(但并不是总能选择最好的方案),MySQL使用基于开销的优化器,预测不同执行计划的开销。

- MySQL不考虑不受它控制的开销,如用户存储过程与用户自定义的函数

- 不考虑正在运行的其他查询

 

2.2 优化数据访问 (这一点很重要)

1. 应用程序是否获取超过需要的数据量?(PS: 多次遇到过查询表所有数据然后再程序中只读取10行之类的代码)

2. MySQL 服务器是否分析了超过需要的行?数据是否没有在存储引擎层被过来掉?(Using index , Using where)

 

典型的错误如下:

1. 提取超过需要的行,然后在程序中只要一部分 (应该使用limit限制数据量)。

2. 多表join提取所有的列 (应该只读取需要的列)。

3. 提取所有的列(提取不需要的列可能导致优化索引失效,增加磁盘IO,浪费内存等, 但如果是知道这个影响并利用查询缓存,简化设计等也是可以考虑的)。

 

访问类型:

Full Table Scan > Index Scan > Range Scan > Unique Index Lookup > Constant.

访问速度以此递增。

对于使用where语句来过滤数据的话,最好到最坏的情况是:

1. 对索引查找用where来消除不匹配的数据行,在存储引擎层。

2. 使用覆盖索引 (Extra 为Using Index) 来避免访问行,取得索引数据后过滤行,发生在MySQL服务器层,但不需要读取行数据。

3. 从表中查询数据,然后过滤 (Using Where), 发生在服务器端并且要读取行数据。

后面会针对执行计划结果做详细介绍。

 

 

2.3 关于执行计划

执行计划结果样例如下图(也可用其他的可视化工具,如mysql workbench):

 

所代表的含义可在官方文档中找到详细说明 ( https://dev.mysql.com/doc/refman/5.5/en/explain-output.html ),

这里说明一些比较重要的结果:

TYPE字段的值:

前面所说的访问速度依次递增就和这个有关:

Full Table Scan > Index Scan > Range Scan > Unique Index Lookup > Constant.

这里列出一些常见的说明:

1、const:  最多匹配一行, 如 SELECT * FROM rental where rental_id=1。

2、eq_ref: 读取的行依次匹配前一个表。

3、ref: 连接仅使用左索引或者索引不是PRIMARY或UNIQUE(或者说得到的不是一行的结果),如果得到的几行数据,这是个比较好的类型。

4、range:  使用索引的范围扫描,如使用了 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()等条件。

5、index: 除了索引树被扫描之外,索引连接类型与ALL相同。这有两种方式:

**************

1. 如果索引是查询的覆盖索引,并满足表中所需的所有数据,则仅扫描索引树。 在这种情况下,Extra列为Using index。 仅索引扫描通常比ALL更快,因为索引的大小通常小于表数据。

2. 使用索引来执行全表扫描,以按索引顺序查找数据行。 在Extra列张则没有Using index,这种情况与ALL的区别是ALL是按行扫描。

**************

6、ALL: 全表扫描,比较糟糕 (但有时候数据比较少的情况下,MySQL会直接进行全表扫描读取数据,效率更高)。

 

 

2.4 优化特定的查询

    查询优化的一个办法是迁移旧数据,腾出内存空间重新平衡索引结构,使得更快的查询速度,很多应用保留半年或三个月的数据都能满足需求,对于旧数据,额外提供平台访问或者在应用层做路由。

2.4.1 优化COUNT (遇到过一知半解的使用,导致想优化却适得其反)

COUNT有两种不同的工作方式:统计值的数量和统计行的数量。

值是一个非空(Non-NULL)的表达式(NULL则表示没有值),如果在COUNT()中定义了列名或其他表达式,COUNT则会统计这个表达式有值(Non-NULL)的次数。

COUNT另外一种工作方式就是统计行数,当MySQL知道括号中的表达式不会为NULL的时候,则使用这种方式,COUNT(*)是个例子,它不会展开成所有列,则是忽略所以的列并统计。

 

2.4.2 优化limit和offset

偏移量很大的查询代价很高,如LIMIT 10000, 10, 则会产生10010数据,然后只截取10行。解决办法:

1. 限制分页能读取的数据页数。

2. 可考虑使用覆盖索引,如 select id, name, description from book limit 100,10;

在ID上有索引改进为:select id, name, description from book  inner join (select id from book limit 100, 10) as b;


本文转自 杰思 51CTO博客,原文链接:http://blog.51cto.com/12700807/1953204

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
17天前
|
缓存 关系型数据库 MySQL
MySQL执行计划选择策略:揭秘查询优化的艺术
【10月更文挑战第15天】 在数据库性能优化中,选择最优的执行计划是提升查询效率的关键。MySQL作为一个强大的关系型数据库管理系统,提供了复杂的查询优化器来生成执行计划。本文将深入探讨如何选择合适的执行计划,以及为什么某些计划更优。
36 2
|
5天前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
10天前
|
监控 PyTorch 数据处理
通过pin_memory 优化 PyTorch 数据加载和传输:工作原理、使用场景与性能分析
在 PyTorch 中,`pin_memory` 是一个重要的设置,可以显著提高 CPU 与 GPU 之间的数据传输速度。当 `pin_memory=True` 时,数据会被固定在 CPU 的 RAM 中,从而加快传输到 GPU 的速度。这对于处理大规模数据集、实时推理和多 GPU 训练等任务尤为重要。本文详细探讨了 `pin_memory` 的作用、工作原理及最佳实践,帮助你优化数据加载和传输,提升模型性能。
41 4
通过pin_memory 优化 PyTorch 数据加载和传输:工作原理、使用场景与性能分析
|
1天前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
9天前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
32 3
|
10天前
|
搜索推荐 关系型数据库 MySQL
mysql like查询优化
通过合理的索引设计、使用全文索引、优化查询结构以及考虑分片和分区表,可以显著提高MySQL中 `LIKE`查询的性能。针对不同的应用场景选择合适的优化策略,能够有效地提升数据库查询效率,减少查询时间。希望这些方法和技巧能帮助您优化MySQL数据库中的模糊查询。
46 4
|
12天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
33 1
|
19天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
51 9
|
13天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
69 1
|
19天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
45 5