基于MySQL 的 SQL 优化总结
文章首发于我的个人博客,欢迎访问。https://blog.itzhouq.cn/mysql1
基于MySQL 的 SQL 优化总结
在数据库运维过程中,优化 SQL 是 DBA 团队的日常任务。例行 SQL 优化,不仅可以提高程序性能,还能减低线上故障的概率。
目前常用的 SQL 优化方式包括但不限于:业务层优化、SQL 逻辑优化、索引优化等。其中索引优化通常通过调整索引或新增索引从而达到 SQL 优化的目的。索引优化往往可以在短时间内产生非常巨大的效果。
--- 来自美团技术团队
SQL 优化是一个复杂的问题,不同版本和种类的数据库、不同数据级的数据需要选择不同的优化策略。
说明:我这里简单总结一下 SQL 优化,很多的大佬写过这方面的细节和用法,甚至还有相关的案例。我只是作为一个阶段性的总结,肯定是不全面的。如有错误和不当之处,欢迎批评指正,不胜感激。
从日常开发写 SQL 的角度看,需要遵循一些规则,但是这些规则只能解决部分问题。因为随着开发和数据量的增长,SQL 还是会变慢,这个时候需要一些针对性的措施,比如针对性地添加索引,通过命令或者工具分析变慢的 SQL 等等。
说说 SQL 优化的其中两个大的原则(肯定还有别的):
原则一:尽量避免全表扫描。
原则二:通过索引优化。
这两个涉及的点比较多,他们之间也是有联系的,下面详细说说。
1、避免全表扫描
为啥要避免全表扫描呢?因为全表扫描耗费更多的时间。
那么从哪些方法避免全表扫描呢?
对 where 和 order by 涉及的列建立索引可以提高访问速度。但是要注意,并不是你建立了索引,索引就一定会生效。如果没有生效查询时还是全表扫描,速度还是得不到提升。那如何判断索引没有生效呢?可以借助 explain + SQL 语句
的结果判断。大佬写的MySQL EXPLAIN 命令: 查看查询执行计划中总结了用法。简单的说,使用该命令分析的结果中很多字段,其中type
描述了查询的方式,如果 type 的结果是ALL
,那么索引肯定没起作用。下面总结一下如何避免索引失效。
1、避免在 where 子句中对字段进行 null 判断
select id from user where name is null
2、避免在 where 子句使用 !=
或者 <>
3、避免在 where 子句中对表达式进行操作
select id from user where age/2 = 20
修改为:
select id from user where age = 20 * 2
4、避免在 where 子句中对字段进行函数操作
5、避免在 like 查询中将 %
放在开头
select id from user where username like '%wh'
2、索引优化
适当地添加索引可以提高 SQL 的速度,但也有些注意点。
1、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则
比如一个索引:
KEY `idx_userid_age` (`userId`, `age`) USING BTREE
符合最左匹配原则的写法是把userid
放在前面
select userid, name from user where userid = 1001 and age = 10
当我们创建的这个联合索引,就相当于创建了(userid)
和(userid, age)
两个索引。联合索引不满足最左原则,一般会失效,但是这个还跟 MySQL 优化器有关系。
2、在适当的时候,使用覆盖索引
通常在使用索引检索数据之后,需要访问磁盘上数据表文件读取所需要的列,这种操作成为“回表”。
若索引中包含查询的所有列,则不需要回表操作,直接从索引文件中读取数据即可,这种索引成为“覆盖索引”。
在查询时尽量减少select *
,只查询需要的行,条件允许时尽量建立覆盖索引。
3、删除冗余索引
索引并不是越多越好,冗余的索引会影响性能。
比如,索引(A, B)
相当于创建了索引(A)
和索引(A, B)
。
4、注意索引的数量
索引不是越多越好,一般不要超过 5 个。索引虽然提高了查询效率,但是也会降低插入和更新的效率。插入或更新可能会重建索引,索引建立索引也需要慎重考虑。
5、索引不适合建立在有大量重复的字段上,如性别这类字段
3、其他
其他原则包括但不限于:
1、查询 SQL 尽量不要使用 select *
,而是 select 某字段
。
2、连表查询的时候尽量将数据量少的表驱动数据多的表。
3、如果插入的数据较多时,考虑批量插入。
4、原则上不要有超过 5 张以上的表连接
阿里巴巴开发手册中规定超过三个表禁止 join的,但是这些规范的适用性还是要考虑环境。当连表数量较少时,连表路径算法选择的是动态规划算法;但是连表太多的情况下,路径算法可能退化成贪心算法,连表的方案可能不是最优的的。
这种情况下,如何写 SQL 呢?答案是通过可以通过冗余实现,细节就不展开了。
4、通过工具分析 SQL
说说几个用到的 SQL 分析工具
4.1 MySQL 自带的慢查询日志
MySQL 的慢查询日志是 MySQL 提供的一种日志,记录,用于记录在 MySQL 中响应时间超过设定的阈值的语句。在 MySQL 的配置文件 my.ini
中开启后,支持将慢查询日志写入文件或者数据库。通过explain
关键词模拟优化器执行 SQL,分析慢查询 SQL。
分析相关语句使用了哪些表、连接的类型、扫描的行数、使用的索引等。
4.2 日志分析工具 MySQLdumpslow
在生产环境中,手工分析日志、查找 SQL 比较费时间。MySQL 提供的 MySQLdumpslow 工具可以得到一些 SQL 访问的统计数据,比如访问次数最多的 10 条 SQL 等。
4.3 第三方工具:美团技术团队的 SQLAdvisor
由美团技术团队维护的一个开源的分析 SQL,给出索引优化建议的工具。
只是大概做了个总结,细节都没有展开,有兴趣的同学自行学习吧。
参考文章:
基于MySQL 的 SQL 优化总结的更多相关文章
- 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)
基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编 ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...
- mysql的sql优化案例
前言 mysql的sql优化器比较弱,选择执行计划貌似很随机. 案例 一.表结构说明mysql> show create table table_order\G***************** ...
- 我的mysql数据库sql优化原则
原文 我的mysql数据库sql优化原则 一.前提 这里的原则 只是针对mysql数据库,其他的数据库 某些是殊途同归,某些还是存在差异.我总结的也是mysql普遍的规则,对于某些特殊情况得特殊对待. ...
- 基于oracle的sql优化
[基于oracle的sql优化] 基于oracle的sql优化 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 一.编写初衷描述 在应有系统开发初期,由于数据库 ...
- 转://从一条巨慢SQL看基于Oracle的SQL优化
http://mp.weixin.qq.com/s/DkIPwbDKIjH2FMN13GkT4w 本次分享的内容是基于Oracle的SQL优化,以一条巨慢的SQL为例,从快速解读SQL执行计划.如何从 ...
- 从一条巨慢SQL看基于Oracle的SQL优化(重磅彩蛋+PPT)
本文根据DBAplus社群第110期线上分享整理而成,文末还有好书送哦~ 讲师介绍 丁俊 新炬网络首席性能优化专家 SQL审核产品经理 DBAplus社群联合发起人.<剑破冰山-Oracle开发 ...
- MySQL之SQL优化详解(二)
目录 MySQL之SQL优化详解(二) 1. SQL的执行顺序 1.1 手写顺序 1.2 机读顺序 2. 七种join 3. 索引 3.1 索引初探 3.2 索引分类 3.3 建与不建 4. 性能分析 ...
- MySQL 慢 SQL & 优化方案
1. 慢 SQL 的危害 2. 数据库架构 & SQL 执行过程 3. 存储引擎和索引的那些事儿 3.1 存储引擎 3.2 索引 4. 慢 SQL 解决之道 4.1 优化分析流程 4.2 执行 ...
- 【MySQL】SQL优化系列之 in与range 查询
首先我们来说下in()这种方式的查询 在<高性能MySQL>里面提及用in这种方式可以有效的替代一定的range查询,提升查询效率,因为在一条索引里面,range字段后面的部分是不生效的. ...
随机推荐
- Fiddler抓取抖音视频
目录 工具 Fiddler配置 手机端配置 工具 Android 或 ios手机均可 Fiddler 下载地址:https://www.telerik.com/fiddler Windows 操作系统 ...
- 即时通信WebSocket 和Socket.IO
WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...
- 前端基础进阶(六)-大厂面试题问题:循环闭包与setTimeout
我在上一篇闭包的文章中留下了一个关于setTimeout与循环闭包的思考题. 利用闭包,修改下面的代码,让循环输出的结果依次为1, 2, 3, 4, 5 for (var i = 1; i <= ...
- php 判断是否手机端还是pc端
来自:https://www.cnblogs.com/webenh/p/5621890.html 用手机访问PC端WWW域名的时候,自动判断跳转到移动端,用电脑访问M域名手机网站的时候,自动跳转到PC ...
- JVM原理与深度调优(三)
jvm垃圾收集算法 1.引用计数算法每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,无法解决对象相互循环引用的问题.还有一个问题是如何解决精准计 ...
- opencv-3-图片存储与相对路径
opencv-3-图片存储与相对路径 opencvqtC++ 在上一篇文章opencv 显示第一副图像 中, 我们完成了一副图像的显示, 包括使用VS,和QT 进行显示.. 本文将展示如何进行图像的显 ...
- Libra教程之:运行自定义move modules
文章目录 简介 创建Move modules 启动本地网络 创建账号并送测试币 编译Move Module 发布编译好的Module 创建交易脚本 编译编译脚本 执行脚本 简介 因为Libra和Mov ...
- php并发加锁
CleverCode在工作项目中,会遇到一些php并发访问去修改一个数据问题,如果这个数据不加锁,就会造成数据的错误.下面CleverCode将分析一个财务支付锁的问题. 1 没有应用锁机制 1.1 ...
- Vector shrink 请求容器降低其容量和size匹配 shrink_to_fit();
一.先从size 和capacity 说起 resize(),设置大小(size); reserve(),设置容量(capacity); size()是分配容器的内存大小,而capacity()只是设 ...
- DAG的深度优先搜索标记
这是图论的基础知识点,也是学习Tarjan的导学课. 一.知识 对于在图G上进行深度优先搜索算法所产生的深度优先森林Gt,我们可以定义四种边的类型: 1.树边(Tree Edge):为深度优先森林中G ...