MySQL-SQL优化

文章目录

    • 1. SQL性能分析
      • 1.1 SQL执行频率
      • 1.2 慢查询日志
      • 1.3 profile详情
      • 1.4 explain
    • 2. SQL优化
      • 2.1 Insert 优化
      • 2.2 Group By 优化
      • 2.3 Order By 优化
      • 2.4 Limit 优化
      • 2.5 Count() 优化
      • 2.6 Update 优化
    • 3. 拓展
      • 3.1 请你说一下MySQL中的性能调优的方法?
      • 3.2 执行 SQL 响应比较慢,你有哪些排查思路?

1. SQL性能分析

1.1 SQL执行频率

  • MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:

    SHOW GLOBAL STATUS LIKE 'Com_______';
    

  • 通过上述指令,我们可以查看到当前数据库到底是以查询为主,还是以增删改为主,从而为数据库优化提供参考依据。 如果是以增删改为主,我们可以考虑不对其进行索引的优化。 如果是以查询为主,那么就要考虑对数据库的索引进行优化了。

1.2 慢查询日志

  • 慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所SQL语句的日志。

  • MySQL的慢查询日志默认没有开启,我们可以查看一下系统变量 slow_query_log。如果要开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

    # 开启MySQL慢日志查询开关
    slow_query_log=1
    # 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
    long_query_time=2
    
  • 查看慢日志文件中记录的信息:/var/lib/mysql/localhost-slow.log

1.3 profile详情

  • show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling参数,能够看到当前MySQL是否支持profile操作:

    SELECT @@have_profiling ;
    

    在这里插入图片描述

  • 可以看到,当前MySQL是支持 profile操作的,但是开关是关闭的。可以通过set语句在session/global级别开启profiling:

    SET profiling = 1;
    
  • 案例:执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:

    -- 查看每一条SQL的耗时基本情况
    show profiles;
    -- 查看指定query_id的SQL语句各个阶段的耗时情况
    show profile for query query_id;
    -- 查看指定query_id的SQL语句CPU的使用情况
    show profile cpu for query query_id;
    

    查看每一条SQL的耗时情况:

    查看指定SQL各个阶段的耗时情况 :

1.4 explain

  • EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。

    EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件 ;
    
  • Explain 执行计划中各个字段的含义:

    字段含义
    idselect查询的序列号,表示查询中执行select子句或者是操作表的顺序 (id相同,执行顺序从上到下;id不同,值越大,越先执行)。
    select_type表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接 或者子查询)、PRIMARY(主查询,即外层的查询)、 UNION(UNION 中的第二个或者后面的查询语句)、 SUBQUERY(SELECT/WHERE之后包含了子查询)等
    type表示连接类型,性能由好到差的连接类型为NULL、system、const、 eq_ref、ref、range、 index、all
    possible_key显示可能应用在这张表上的索引,一个或多个。
    key实际使用的索引,如果为NULL,则没有使用索引。
    key_len表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长 度,在不损失精确性的前提下, 长度越短越好 。
    rowsMySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值, 可能并不总是准确的。
    filtered表示返回结果的行数占需读取行数的百分比, filtered 的值越大越好。

2. SQL优化

2.1 Insert 优化

  1. 使用一条SQL语句插入多条数据而不是多条SQL语句

    • 在 MySQL 中,插入多条数据有 2 种方式。第一种是使用一个 INSERT 语句插入多条数据。INSERT 语句的情形如下:

      INSERT INTO items(name,city,price,number,picture) VALUES ('耐克运动鞋','广州',500,1000,'001.jpg'),('耐克运动鞋 2','广州 2',500,1000,'002.jpg');
      
    • 第二种是一个 INSERT 语句只插入一条数据,执行多个 INSERT 语句来插入多条数据。INSERT 语句的情形如下:

      INSERT INTO items(name,city,price,number,picture) VALUES('耐克运动鞋','广州',500,1000,'001.jpg');
      INSERT INTO items(name,city,price,number,picture) VALUES('耐克运动鞋 2','广州',500,1000,'002.jpg');
      

      一次性插入多条数据和多次插入数据所耗费的时间是不一样的。第一种方式减少了与数据库之间的连接等操作,其速度比第二种方式要快一些。所以插入大量数据时,建议使用第一种方法。

  2. 手动提交事务MySQL 的事务自动提交模式默认是开启的,其对 MySQL 的性能也有一定得影响。比如你插入了 1000 条数据,MySQL 就会提交 1000 次,这大大影响了插入数据的速度。而如果我们把自动提交关掉,通过程序来控制,只要一次提交就可以了。

    start transaction;
    insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');
    insert into tb_test values(4,'Tom'),(5,'Cat'),(6,'Jerry');
    insert into tb_test values(7,'Tom'),(8,'Cat'),(9,'Jerry');
    commit;
    
  3. 主键顺序插入,性能要高于乱序插入:

    主键乱序插入 : 8 1 9 21 88 2 4 15 89 5 7 3
    主键顺序插入 : 1 2 3 4 5 7 8 9 15 21 88 89
    
  4. 如果一次性需要插入大批量数据(比如: 几百万的记录),使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。可以执行如下指令,将数据脚本文件中的数据加载到表结构中:

    -- 客户端连接服务端时,加上参数 -–local-infile
    mysql –-local-infile -u root -p
    -- 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
    set global local_infile = 1;
    -- 执行load指令将准备好的数据,加载到表结构中
    load data local infile '/root/sql1.log' into table tb_user fields
    terminated by ',' lines terminated by '\n' ;
    

2.2 Group By 优化

  • 在分组操作中,我们需要通过以下两点进行优化,以提升性能:
    1. 在分组操作时,可以通过索引来提高效率。
    2. 分组操作时,索引的使用也是满足最左前缀法则的。

2.3 Order By 优化

  • MySQL的排序,有两种方式:

    1. Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序

    2. Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。

      以上两种Using index的性能高,而Using filesort的性能低,我们在优化排序操作时,尽量要优化为 Using index。

  • 优化原则:

    1. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
    2. 尽量使用覆盖索引。
    3. 多字段排序, 一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
    4. 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。

2.4 Limit 优化

  • 在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。

  • 优化思路: 一般分页查询时,通过创建 覆盖索引 能够比较好地提高性能,可以通过覆盖索引+子查询形式进行优化。

    select * from tb_sku t , (select id from tb_sku order by id limit 2000000,10) a where t.id = a.id;
    

2.5 Count() 优化

  • count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加,最后返回累计值。

  • 用法:count(*)、count(主键)、count(字段)、count(数字):

    count用 法含义
    count(主 键)InnoDB 引擎会遍历整张表,把每一行的 主键id 值都取出来,返回给服务层。 服务层拿到主键后,直接按行进行累加(主键不可能为null)
    count(字 段)没有not null 约束 : InnoDB 引擎会遍历整张表把每一行的字段值都取出 来,返回给服务层,服务层判断是否为null,不为null,计数累加。 有not null 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返 回给服务层,直接按行进行累加。
    count(数 字)InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1” 进去,直接按行进行累加。
    count(*)InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接 按行进行累加。

    按照效率排序的话,count(字段) < count(主键 id) < count(1) ≈ count(星),所以尽量使用 count(星)。

2.6 Update 优化

  • 尽量使用索引作为修改的限制条件,这样MySQL的锁是行锁,性能更高,否则行锁将升级为表锁。

  • 案例:表中有两个字段分别是idname,其中只有id为主键索引。

    1. 行锁:

      update course set name = 'javaEE' where id = 1 ;
      
    2. 表锁:

      update course set name = 'SpringBoot' where name = 'PHP' ;
      

3. 拓展

3.1 请你说一下MySQL中的性能调优的方法?

  • Mysql 性能调优方法可以从四个方面来说,分别是:表结构与索引SQL 语句优化Mysql 参数优化硬件及系统配置

  1. 硬件及系统配置:硬件方面、主要是 CPU 核数、磁盘的读写性能(减小寻道时间、旋转时间、传输时间),可以选择 SSD、网卡、内存等方面。
  2. MySQL参数优化:主要可以设置 Buffer_pool 的大小,建议占总内存的 70%左右。设置刷盘策略,平衡好数据安全性和性能的关系等。
  3. SQL语句优化:
    1. 通过慢查询分析需要优化的 SQL 进行合理优化、利用 explain、profile 等工具分析 SQL执行计划。
    2. 少用Select * ,多用Count(*),避免返回不必要的数据列 。
    3. 尽量使用表连接代替子查询,表连接尽量使用内连接(inner join)而不是外连接(left join、right join),内接时以小表驱动大表。
  4. 表结构与索引:
    1. 表结构优化:
      • 有些表在设计时设置了很多的字段,而有些字段的使用频率非常低。这样当这个表的数据量很大时,查询数据的速度
        就会很慢。对于这种情况,我们可以将这些使用频率较低的字段分离出来形成新表
      • 表连接会降低数据库的查询速度,所以对于经常使用表连接查询的表,我们可以建立中间表来提高查询速度。
      • 一般情况下,设计数据库时应尽量让表符合三大范式。但是,有时为了提高查询速度,可以有意识地在表中增加冗余字段
      • 选择合适的字段类型,比如charvarchar性能更高、tinyintint占据空间更小。
    2. 索引方面的优化及相关知识,可以参考博主的另一篇文章:MySQL-索引(INDEX)-CSDN博客。
  5. 架构设计层面的优化:MySQL 是一个磁盘 IO 访问量非常频繁的关系型数据库在高并发和高性能的场景中。MySQL 数据库必然会承受巨大的并发压力,而此时,我们的优化方式可以分为几个部分。
    1. 搭建 Mysql 主从集群,单个 Mysql 服务容易单点故障,一旦服务器宕机,将会导致依赖 Mysql 数据库的应用全部无法响应。 主从集群或者主主集群可以保证服务的高可用性。
    2. 读写分离设计,在读多写少的场景中,通过读写分离的方案,可以避免读写冲突导致的性能影响。
    3. 引入分库分表机制,通过分库可以降低单个服务器节点的 IO 压力,通过分表的方式可以降低单表数据量,从而提升 sql 查询的效率。
    4. 针对热点数据可以引入更为高效的分布式数据库,比如 Redis、MongoDB 等,他们可以很好的缓解 Mysql 的访问压力,同时还能提升数据检索性能。

3.2 执行 SQL 响应比较慢,你有哪些排查思路?

  • 如果执行 SQL 响应比较慢,我觉得可能有以下 4 个原因:

  1. 索引失效:首先,可以打开 MySQL 的慢查询日志,收集一段时间的慢查询日志内容,然后找出耗时最长的 SQL 语句,对这些 SQL 语句进行分析。 比如可以利用执行计划 explain 去查看 SQL 是否有命中索引。如果发现慢查询的 SQL 没有命中索引,可以尝试去优化这些 SQL 语句,保证 SQL 走索引执行。如果 SQL 结构没有办法优化的话,可以考虑在表上再添加对应的索引。

  2. 单表数据量数据过多,导致查询瓶颈的情况。即使 SQL 语句走了索引,表现性能也不会特别好。这个时候我们需要考虑对表进行切分。表切分规则一般分为两种,一种是水平切分,一种是垂直切分

    • 水平切分:把一张数据行数达到千万级别的大表,按照业务主键切分为多张小表,这些小表可能达到 100 张甚至 1000 张。

    • 垂直切分:将一张单表中的多个列,按照业务逻辑把关联性比较大的列放到同一张表中去。

  3. 网络原因或者机器负载过高的情况,我们可以进行读写分离:比如 MySQL 支持一主多从的分布式部署,我们可以将主库只用来处理写数据的操作而多个从库只用来处理读操作。在流量比较大的场景中,可以增加从库来提高数据库的负载能力,从而提升数据库的总体性能。

  4. 热点数据导致单点负载不均衡的情况:除了对数据库本身的调整以外,还可以增加缓存。将查询比较频繁的热点数据预存到缓存当中,比如 Redis、MongoDB、ES 等,以此来缓解数据的压力,从而提高数据库的响应速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆的概念实现

前言 本文将详细讲解堆。堆是一种二叉树&#xff08;一般是完全二叉树&#xff09;使用顺序结构的数组来存储。 tip&#xff1a;这里我们需要注意区分堆在不同地方的含义&#xff0c;这里的堆是一个数据结构&#xff0c;操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块…

kubernetes镜像仓库harbor

一、镜像仓库的种类 GitHub GitHub有付费版和免费版,目前默认的docker镜像拉取策略是从GitHub上进行拉取gitee 国内harbor私有仓库二、harbor仓库规划设计 私有镜像仓库 Harbor 安装和配置 新创建一台虚拟机安装harbor, 配置如下: 主机名ip配置网络harbor192.168.1.204VCPU/…

「深度学习」长短时记忆网络LSTM

一、经典模型 \widetilde{c}^{<t>} tanh(w_{c}[a^{<t-1>},x^{<t>}]b_{c}) 更新门&#xff1a;\Gamma_{u} \sigma(w_{u}[a^{<t-1>},x^{<t>}]b_{u}) 遗忘门&#xff1a;\Gamma_{f} \sigma(w_{f}[a^{<t-1>},x^{<t>}]b_{f}) 输出门…

svg 进阶

svg 进阶 svg 应用场景 绘制 icon绘制动画 svg viewport 和 viewBox viewport 是 svg 图像的可见区域 viewBox 是用于在画布上绘制 svg 图形的坐标系统 在一下案例中 svg中 width“500” height“200” 就是可视区域 比如你的svg是100X100但是你的可视区域只有20X20 那么他…

职业性格测试在求职应聘跳槽中的应用

人的性格总是千奇百怪&#xff0c;有的人总是想迎接挑战&#xff0c;超越自己&#xff0c;不停的奔着高处走&#xff0c;然而有的人总是喜欢随遇而安&#xff0c;踏踏实实一辈子&#xff0c;有份安稳的工作&#xff0c;有吃有喝就好。那么对于哪些喜欢迎接挑战&#xff0c;但又…

《MySQL 简易速速上手小册》第4章:数据安全性管理(2024 最新版)

文章目录 4.1 用户认证和权限控制4.1.1 基础知识4.1.2 重点案例&#xff1a;使用 Python 管理 MySQL 用户权限4.1.3 拓展案例 4.2 防止 SQL 注入和其他安全威胁4.2.1 基础知识4.2.2 重点案例&#xff1a;使用 Python 和 MySQL 进行安全的数据查询4.2.3 拓展案例 4.3 数据加密和…

边缘人工智能的发展 —— 边缘AI图形化开发

1、背景 边缘人工智能是指直接在边缘设备上运行的机器学习算法的形式使用人工智能。这里的“边缘设备”指的是网络边缘的设备&#xff0c;例如智能手机、传感器、工业机器人等。这些设备具备数据处理和机器学习算法运行的能力&#xff0c;可以在本地进行必要的数据操作并发送&…

Android Studio无法安装Git问题解决(折中方案)

安装配置好studio&#xff0c;往往会使用git克隆github上面的项目&#xff0c;但是却发现git无法正确安装&#xff0c;本文将介绍如何解决git无法安装这一问题。 对于git安装&#xff0c;实际比较复杂&#xff0c;可以参考这一篇博客。 Git 详细安装教程&#xff08;详解 Gi…

二维差分---三维差分算法笔记

文章目录 一.二维差分构造差分二维数组二维差分算法状态dp求b[i][j]数组的二维前缀和图解 二.三维前缀和与差分三维前缀和图解:三维差分核心公式图解:模板题 一.二维差分 给定一个原二维数组a[i][j],若要给a[i][j]中以(x1,y1)和(x2,y2)为对角线的子矩阵中每个数都加上一个常数…

Java SE多态

文章目录 1.多态&#xff1a;1.1.什么是多态&#xff1a;1.2.多态实现条件&#xff1a;1.2.1.重写&#xff1a;1.2.2.向上转型&#xff1a; 1.多态&#xff1a; 1.1.什么是多态&#xff1a; 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去…

54.螺旋矩阵(Java)

题目描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 输入&#xff1a; matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a; [1,2,3,6,9,8,7,4,5] 代码实现&#xff1a; import java.util.ArrayLi…

【数据结构与算法】力扣刷题记之 稀疏数组

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

总结:图像生成网络

1、最新的几款图像生成网络 eCNN 文献&#xff1a;Bahrami A, Karimian A, Fatemizadeh E, et al. A new deep convolutional neural network design with efficient learning capability: Application to CT image synthesis from MRI[J]. Medical physics, 2020, 47(10): 515…

Qt PCL学习(三):点云滤波

注意事项 版本一览&#xff1a;Qt 5.15.2 PCL 1.12.1 VTK 9.1.0前置内容&#xff1a;Qt PCL学习&#xff08;一&#xff09;&#xff1a;环境搭建、Qt PCL学习&#xff08;二&#xff09;&#xff1a;点云读取与保存 0. 效果演示 1. pcl_open_save.pro QT core guigr…

包装效果图为何要用云渲染100?渲染100邀请码1a12

包装效果图能吸引用户注意力&#xff0c;提升销量&#xff0c;随着技术的发展&#xff0c;越来越多的设计师开始使用云渲染来处理效果图&#xff0c;云渲染有什么优势呢&#xff1f;以渲染100为例我来说下。 1、节省时间和成本 渲染100拥有超过10万台的高性能渲染节点&#x…

【Larry】英语学习笔记语法篇——换一种方式理解词性

目录 一、换一种方式理解词性 1、名词、形容词、副词&#xff0c;这就是一切 2、词性之间的修饰关系 3、介词其实很简单 形容词属性的介词短语 副词属性的介词短语 ①修饰动词 ②修饰形容词 ③修饰其他副词 一、换一种方式理解词性 1、名词、形容词、副词&#xff0c…

(基础算法)归并排序

1.确定分界点 mid &#xff08;lr&#xff09;/2 2.递归排序左右两段 3.归并----合二为一 #include<iostream> using namespace std; //归并排序----分治 const int N10010; int n; int q[N],tmp[N];//需要一个额外数组void mergesort(int q[],int l,int r)//l左边界&a…

TCP 传输控制协议——详细

目录 1 TCP 1.1 TCP 最主要的特点 1.2 TCP 的连接 TCP 连接&#xff0c;IP 地址&#xff0c;套接字 1.3 可靠传输的工作原理 1.3.1 停止等待协议 &#xff08;1&#xff09;无差错情况 &#xff08;2&#xff09;出现差错 &#xff08;3&#xff09;确认丢失和确认迟到…

【MySQL进阶之路】BufferPool底层设计(下)

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

Linux运用fork函数创建进程

fork函数&#xff1a; 函数原型&#xff1a; pid_t fork(void); 父进程调用fork函数创建一个子进程&#xff0c;子进程的用户区父进程的用户区完全一样&#xff0c;但是内核区不完全一样&#xff1b;如父进程的PID和子进程的PID不一样。 返回值&#xff1a; RETURN VALUEO…