我不得不告诉大家的MySQL优化“套路”(一)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 说起 MySQL 的查询优化,相信大家收藏了一堆奇技淫巧:不能使用 SELECT *、不使用 NULL 字段、合理创建索引、为字段选择合适的数据类型.....

你是否真的理解这些优化技巧?是否理解它背后的工作原理?在实际场景下性能真有提升吗?我想未必。


因而理解这些优化建议背后的原理就显得尤为重要,希望本文能让你重新审视这些优化建议,并在实际业务场景下合理的运用。


MySQL 逻辑架构


如果能在头脑中构建一幅 MySQL 各组件之间如何协同工作的架构图,将有助于深入理解 MySQL 服务器。下图是 MySQL 的逻辑架构图:

                              20.jpg

MySQL 逻辑架构


MySQL 的逻辑架构整体分为三层,最上层为客户端层,并非 MySQL 所独有,诸如:连接处理、授权认证、安全等功能均在这一层处理。


MySQL 的大多数核心服务均在中间这一层,包括查询解析、分析、优化、缓存、内置函数(比如:时间、数学、加密等函数)。所有的跨存储引擎的功能也在这一层实现:存储过程、触发器、视图等。


最下层为存储引擎,负责 MySQL 中的数据存储和提取。和 Linux 下的文件系统类似,每种存储引擎都有其优势和劣势。


中间的服务层通过 API 与存储引擎通信,这些 API 接口屏蔽了不同存储引擎间的差异。


MySQL 查询过程


我们总是希望 MySQL 能够获得更高的查询性能,最好的办法是弄清楚 MySQL 是如何优化和执行查询的。


一旦理解了这一点,就会发现:很多的查询优化工作实际上就是遵循一些原则让 MySQL 的优化器能够按照预想的合理方式运行。


当向 MySQL 发送一个请求的时候,MySQL 到底做了些什么呢?

21.jpg


MySQL 查询过程


客户端/服务端通信协议


MySQL 的客户端/服务端通信协议是“半双工”的:在任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,这两个动作不能同时发生。


一旦一端开始发送消息,另一端要接收完整个消息才能响应它,所以我们无法也无须将一个消息切成小块独立发送,也没有办法进行流量控制。


客户端用一个单独的数据包将查询请求发送给服务器,所以当查询语句很长的时候,需要设置 max_allowed_packet 参数。


但是需要注意的是,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常。


与之相反的是,服务器响应给用户的数据通常会很多,由多个数据包组成。但是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。


因而在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯,这也是查询中尽量避免使用 SELECT * 以及加上 LIMIT 限制的原因之一。



查询缓存


在解析一个查询语句前,如果查询缓存是打开的,那么 MySQL 会检查这个查询语句是否命中查询缓存中的数据。


如果当前查询恰好命中查询缓存,在检查一次用户权限后直接返回缓存中的结果。这种情况下,查询不会被解析,也不会生成执行计划,更不会执行。


MySQL 将缓存存放在一个引用表(不要理解成 table,可以认为是类似于 HashMap 的数据结构),通过一个哈希值索引。


这个哈希值通过查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息计算得来。


所以两个查询在任何字符上的不同(例如:空格、注释),都会导致缓存不会命中。


如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果都不会被缓存。


比如函数 NOW() 或者 CURRENT_DATE() 会因为不同的查询时间,返回不同的查询结果。


再比如包含 CURRENT_USER 或者 CONNECION_ID() 的查询语句会因为不同的用户而返回不同的结果,将这样的查询结果缓存起来没有任何的意义。


既然是缓存,就会失效,那查询缓存何时失效呢?MySQL 的查询缓存系统会跟踪查询中涉及的每个表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。


正因为如此,在任何的写操作时,MySQL 必须将对应表的所有缓存都设置为失效。


如果查询缓存非常大或者碎片很多,这个操作就可能带来很大的系统消耗,甚至导致系统僵死一会儿。


而且查询缓存对系统的额外消耗也不仅仅在写操作,读操作也不例外:

  • 任何的查询语句在开始之前都必须经过检查,即使这条 SQL 语句永远不会命中缓存。
  • 如果查询结果可以被缓存,那么执行完成后,会将结果存入缓存,也会带来额外的系统消耗。


基于此,我们要知道并不是什么情况下查询缓存都会提高系统性能,缓存和失效都会带来额外消耗,只有当缓存带来的资源节约大于其本身消耗的资源时,才会给系统带来性能提升。


但如何评估打开缓存是否能够带来性能提升是一件非常困难的事情,也不在本文讨论的范畴内。


如果系统确实存在一些性能问题,可以尝试打开查询缓存,并在数据库设计上做一些优化,比如:

  • 用多个小表代替一个大表,注意不要过度设计。
  • 批量插入代替循环单条插入。
  • 合理控制缓存空间大小,一般来说其大小设置为几十兆比较合适。
  • 可以通过 SQL_CACHE 和 SQL_NO_CACHE 来控制某个查询语句是否需要进行缓存。


最后的忠告是不要轻易打开查询缓存,特别是写密集型应用。如果你实在是忍不住,可以将 query_cache_type 设置为 DEMAND。


这时只有加入 SQL_CACHE 的查询才会走缓存,其他查询则不会,这样可以非常自由地控制哪些查询需要被缓存。


当然查询缓存系统本身是非常复杂的,这里讨论的也只是很小的一部分,其他更深入的话题没有涉及,比如:缓存是如何使用内存的?如何控制内存的碎片化?事务对查询缓存有何影响等等。


语法解析和预处理


MySQL 通过关键字将 SQL 语句进行解析,并生成一棵对应的解析树。这个过程解析器主要通过语法规则来验证和解析。比如 SQL 中是否使用了错误的关键字或者关键字的顺序是否正确等等。


预处理则会根据 MySQL 规则进一步检查解析树是否合法。比如检查要查询的数据表和数据列是否存在等等。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
120 9
|
2月前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
2天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
30 16
|
3天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
18 7
|
27天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
66 18
|
26天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
36 7
|
25天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
69 5
|
2月前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
61 2
|
2月前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
156 3
下一篇
开通oss服务