0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

你会从哪些维度进行MySQL性能优化?2

jf_78858299 来源:蝉沐风的码场 作者:蝉沐风 2023-03-03 10:23 次阅读

3. 优化器——SQL分析与优化

处理完连接、优化完缓存等架构的事情,SQL查询语句来到了解析器和优化器的地盘了。在这一步如果出了任何问题,那就只能是SQL语句的问题了。

只要你的语法不出问题,解析器就不会有问题。此外,为了防止你写的SQL运行效率低,优化器会自动做一些优化,但如果实在是太烂,优化器也救不了你了,只能眼睁睁地看着你的SQL查询沦为 慢查询

3.1 慢查询

慢查询就是执行地很慢的查询(这句话说得跟废话似的。。。),只有知道MySQL中有哪些慢查询我们才能针对性地进行优化。

因为开启慢查询日志是有性能代价的,因此MySQL默认是关闭慢查询日志功能,使用以下命令查看当前慢查询状态

mysql> show variables like 'slow_query%';
+---------------------+--------------------------------------+
| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_query_log      | OFF                                  |
| slow_query_log_file | /var/lib/mysql/9e74f9251f6c-slow.log |
+---------------------+--------------------------------------+
2 rows in set (0.00 sec)

slow_query_log表示当前慢查询日志是否开启,slow_query_log_file表示慢查询日志的保存位置。

除了上面两个变量,我们还需要确定“慢”的指标是什么,即执行超过多长时间才算是慢查询,默认是10S,如果改成0的话就是记录所有的SQL。

mysql> show variables like '%long_query%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

3.1.1 打开慢日志

有两种打开慢日志的方式

  1. 修改配置文件my.cnf

此种修改方式系统重启后依然有效

# 是否开启慢查询日志
slow_query_log=ON
# 
long_query_time=2
slow_query_log_file=/var/lib/mysql/slow.log
  1. 动态修改参数(重启后失效)
mysql> set @@global.slow_query_log=1;
Query OK, 0 rows affected (0.06 sec)

mysql> set @@global.long_query_time=2;
Query OK, 0 rows affected (0.00 sec)

3.1.2 慢日志分析

MySQL不仅为我们保存了慢日志文件,还为我们提供了慢日志查询的工具mysqldumpslow,为了演示这个工具,我们先构造一条慢查询:

mysql> SELECT sleep(5);

然后我们查询用时最多的1条慢查询:

[root@iZ2zejfuakcnnq2pgqyzowZ ~]# mysqldumpslow -s t -t 1 -g 'select' /var/lib/mysql/9e74f9251f6c-slow.log

Reading mysql slow query log from /var/lib/mysql/9e74f9251f6c-slow.log
Count: 1  Time=10.00s (10s)  Lock=0.00s (0s)  Rows=1.0 (1), root[root]@localhost
  SELECT sleep(N)

其中,

  • Count :表示这个SQL执行的次数
  • Time :表示执行的时间,括号中的是累积时间
  • Locks :表示锁定的时间,括号中的是累积时间
  • Rows :表示返回的记录数,括号中的是累积数

更多关于mysqldumpslow的使用方式,可以查阅官方文档,或者执行mysqldumpslow --help寻求帮助。

3.2 查看运行中的线程

我们可以运行show full processlist查看MySQL中运行的所有线程,查看其状态和运行时间,找到不顺眼的,直接kill。

图片

image-20220405182328247

其中,

  • Id :线程的唯一标志,可以使用Id杀死指定线程
  • User :启动这个线程的用户,普通账户只能查看自己的线程
  • Host :哪个ip和端口发起的连接
  • db :线程操作的数据库
  • Command :线程的命令
  • Time :操作持续时间,单位秒
  • State :线程的状态
  • Info :SQL语句的前100个字符

3.3 查看服务器运行状态

使用SHOW STATUS查看MySQL服务器的运行状态,有sessionglobal两种作用域,一般使用like+通配符进行过滤。

-- 查看select的次数
mysql> SHOW GLOBAL STATUS LIKE 'com_select';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| Com_select    | 168241 |
+---------------+--------+
1 row in set (0.05 sec)

3.4 查看存储引擎运行信息

SHOW ENGINE用来展示存储引擎的当前运行信息,包括事务持有的表锁、行锁信息;事务的锁等待情况;线程信号量等待;文件IO请求;Buffer pool统计信息等等数据。

例如:

SHOW ENGINE INNODB STATUS;

上面这条语句可以展示innodb存储引擎的当前运行的各种信息,大家可以据此找到MySQL当前的问题,限于篇幅不在此意义说明其中信息的含义,大家只要知道MySQL提供了这样一个监控工具就行了,等到需要的时候再来用就好。

3.5 EXPLAIN执行计划

通过慢查询日志我们可以知道哪些SQL语句执行慢了,可是为什么慢?慢在哪里呢?

MySQL提供了一个执行计划的查询命令EXPLAIN,通过此命令我们可以查看SQL执行的计划,所谓执行计划就是:优化器会不会优化我们自己书写的SQL语句(比如外连接改内连接查询,子查询优化为连接查询...)、优化器针对此条SQL的执行对哪些索引进行了成本估算,并最终决定采用哪个索引(或者最终选择不用索引,而是全表扫描)、优化器对单表执行的策略是什么,等等等等。

EXPLAIN在MySQL5.6.3之后也可以针对UPDATE、DELETE和INSERT语句进行分析,但是通常情况下我们还是用在SELECT查询上。

这篇文章主要是从宏观上多个角度介绍MySQL的优化策略,因此这里不详细说明EXPLAIN的细节,之后单独成篇。

3.6 SQL与索引优化

3.6.1 SQL优化

SQL优化指的是SQL本身语法没有问题,但是有实现相同目的的更好的写法。比如:

  • 使用小表驱动大表;用join改写子查询;or改成union
  • 连接查询中,尽量减少驱动表的扇出(记录数),访问被驱动表的成本要尽量低,尽量在被驱动表的连接列上建立索引,降低访问成本;被驱动表的连接列最好是该表的主键或者是唯一二级索引列,这样被驱动表的成本会降到更低
  • 大偏移量的limit,先过滤再排序

针对最后一条举个简单的例子,下面两条语句能实现同样的目的,但是第二条的执行效率比第一条执行效率要高得多(存储引擎使用的是InnoDB),大家感受一下:

-- 1. 大偏移量的查询
mysql> SELECT * FROM user_innodb LIMIT 9000000,10;
Empty set (8.18 sec)

-- 2.先过滤ID(因为ID使用的是索引),再limit
mysql> SELECT * FROM user_innodb WHERE id > 9000000 LIMIT 10;
Empty set (0.02 sec)

3.6.2 索引优化

为慢查询创建适当的索引是个非常常见并且非常有效的方法,但是索引是否会被高效使用又是另一门学问了。

4. 存储引擎与表结构

4.1 选择存储引擎

一般情况下,我们会选择MySQL默认的存储引擎存储引擎InnoDB,但是当对数据库性能要求精益求精的时候,存储引擎的选择也成为一个关键的影响因素。

建议根据不同的业务选择不同的存储引擎,例如:

  • 查询操作、插入操作多的业务表,推荐使用MyISAM
  • 临时表使用Memory
  • 并发数量大、更新多的业务选择使用InnoDB
  • 不知道选啥直接默认。

4.2 优化字段

字段优化的最终原则是: 使用可以正确存储数据的最小的数据类型

4.2.1 整数类型

MySQL提供了6种整数类型,分别是

  • tinyint
  • smallint
  • mediumint
  • int
  • integer
  • bigint

不同的存储类型的最大存储范围不同,占用的存储的空间自然也不同。

例如,是否被删除的标识,建议选用tinyint,而不是bigint

4.2.2 字符类型

你是不是直接把所有字符串的字段都设置为varchar格式了?甚至怕不够,还会直接设置成varchar(1024)的长度?

如果不确定字段的长度,肯定是要选择varchar,但是varchar需要额外的空间来记录该字段目前占用的长度;因此如果字段的长度是固定的,尽量选用char,这会给你节约不少的内存空间。

4.2.3 非空

非空字段尽量设置成NOT NULL,并提供默认值,或者使用特殊值代替NULL

因为NULL类型的存储和优化都会存在性能不佳的问题,具体原因在这里就不展开了。

4.2.4 不要用外键、触发器和视图功能

这也是「阿里巴巴开发手册」中提到的原则。原因有三个:

  1. 降低了可读性,检查代码的同时还得查看数据库的代码;
  2. 把计算的工作交给程序,数据库只做好存储的工作,并把这件事情做好;
  3. 数据的完整性校验的工作应该由开发者完成,而不是依赖于外键,一旦用了外键,你会发现测试的时候随便删点垃圾数据都变得异常艰难。

4.2.5 图片、音频视频存储

不要直接存储大文件,而是要存储大文件的访问地址。

4.2.6 大字段拆分和数据冗余

大字段拆分其实就是前面说过的垂直分表,把不常用的字段或者数据量较大的字段拆分出去,避免列数过多和数据量过大,尤其是习惯编写SELECT *的情况下,列数多和数据量大导致的问题会被严重放大!

字段冗余原则上不符合数据库设计范式,但是却非常有利于快速检索。比如,合同表中存储客户id的同时可以冗余存储客户姓名,这样查询时就不需要再根据客户id获取用户姓名了。因此针对业务逻辑适当做一定程度的冗余也是一种比较好的优化技巧。

5. 业务优化

严格来说,业务方面的优化已经不算是MySQL调优的手段了,但是业务的优化却能非常有效地减轻数据库访问压力,这方面一个典型例子就是淘宝,下面举几个简单例子给大家提供一下思路:

  1. 以往都是双11当晚开始买买买的模式,最近几年双11的预售战线越拉越长,提前半个多月就开始了,而且各种定金红包模式丛出不穷,这种方式叫做 预售分流 。这样做可以分流客户的服务请求,不必等到双十一的凌晨一股脑地集体下单;
  2. 双十一的凌晨你或许想查询当天之外的订单,但是却查询失败;甚至支付宝里的小鸡的口粮都被延迟发放了,这是一种 降级策略 ,集结不重要的服务的计算资源,用来保证当前最核心的业务;
  3. 双十一的时候支付宝极力推荐使用花呗支付,而不是银行卡支付,虽然一部分考量是提高软件粘性,但是另一方面,使用余额宝实际使用的阿里内部服务器,访问速度快,而使用银行卡,需要调用银行接口,相比之下操作要慢了许多。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6514

    浏览量

    87610
  • 服务器
    +关注

    关注

    12

    文章

    8125

    浏览量

    82543
  • MySQL
    +关注

    关注

    1

    文章

    775

    浏览量

    26006
  • 服务端
    +关注

    关注

    0

    文章

    62

    浏览量

    6871
收藏 人收藏

    评论

    相关推荐

    MySQL的执行过程 SQL语句性能优化常用策略

    回顾 MySQL 的执行过程,帮助介绍如何进行 sql 优化
    的头像 发表于 12-12 10:26 315次阅读
    <b class='flag-5'>MySQL</b>的执行过程 SQL语句<b class='flag-5'>性能</b><b class='flag-5'>优化</b>常用策略

    mysql中文参考手册chm

    数据库表类型 10 MySQL 得到最大的性能 10.1 优化概述 10.2 系统/编译时和启动参数的调节 10.2.1 编译和链接如何影响 M
    发表于 12-26 13:32

    0基础学Mysql:mysql入门视频教程!

    互联网行业的高速发展,各个中小企业的数据库存放的数据,也已经达到了一个相当高的数量级。学习目标:深入理解MySQL数据库的原理硬件 系统 MySQL参数 执行计划 SQL优化等多角度
    发表于 07-08 10:51

    全球唯一:MySQL社区2018年度公司贡献奖颁给阿里云

    SemiSync 原有 PLUGIN 的方式,进行静态化编译和优化,至少提升10%的性能。8. 上百个 InnoDB Engine 缺限和优化补丁AliSQL 针对 InnoDB E
    发表于 04-25 11:51

    Mysql优化选择最佳索引规则

    每个表添加一个列的列表。2. 在任何索引中最左边的列应与查询相等比较匹配,可以添加多个列,只要所有列与常量进行比较相等即可。3.选择一个列,这将是范围列,MySQL 在每个索引中只支持一个范围列,需使用范围运算符(, >,
    发表于 07-06 15:13

    mysql数据库优化方案

    MySQL千万级大表优化解决方案
    发表于 08-19 12:18

    mysql的查询优化

    mysql查询优化
    发表于 03-12 11:06

    MySQL优化之查询性能优化之查询优化器的局限性与提示

    MySQL优化三:查询性能优化之查询优化器的局限性与提示
    发表于 06-02 06:34

    MySQL索引使用优化和规范

    MySQL - 索引使用优化和规范
    发表于 06-15 16:01

    MySql5.6性能优化最佳实践

    MySql5.6性能优化最佳实践
    发表于 09-08 08:47 13次下载
    <b class='flag-5'>MySql</b>5.6<b class='flag-5'>性能</b><b class='flag-5'>优化</b>最佳实践

    MySQL数据库:理解MySQL性能优化优化查询

    最近一直在为大家更新MySQL相关学习内容,可能有朋友不懂MySQL的重要性。在程序,语言,架构更新换代频繁的今天,MySQL 恐怕是大家使用最多的存储数据库了。由于MySQL
    的头像 发表于 07-02 17:18 2795次阅读
    <b class='flag-5'>MySQL</b>数据库:理解<b class='flag-5'>MySQL</b>的<b class='flag-5'>性能</b><b class='flag-5'>优化</b>、<b class='flag-5'>优化</b>查询

    MySQL 5.7与MySQL 8.0 性能对比

    背景 测试mysql5.7和mysql8.0分别在读写,选定,只写模式下不同并发时的性能(tps,qps) 最早 测试使用版本为mysql5.7.22和
    的头像 发表于 11-03 09:26 1.4w次阅读
    <b class='flag-5'>MySQL</b> 5.7与<b class='flag-5'>MySQL</b> 8.0 <b class='flag-5'>性能</b>对比

    你会从哪些维度进行MySQL性能优化?1

    你会从哪些维度进行MySQL性能优化?你会怎么回答? 所谓的性能
    的头像 发表于 03-03 10:23 331次阅读
    你会从哪些<b class='flag-5'>维度</b><b class='flag-5'>进行</b><b class='flag-5'>MySQL</b><b class='flag-5'>性能</b><b class='flag-5'>优化</b>?1

    MySQL性能优化方法

    MySQL 性能优化是一项关键的任务,可以提高数据库的运行速度和效率。以下是一些优化方法,包括具体代码和详细优化方案。
    的头像 发表于 11-22 09:59 270次阅读

    MySQL执行过程:如何进行sql 优化

    (1)客户端发送一条查询语句到服务器; (2)服务器先查询缓存,如果命中缓存,则立即返回存储在缓存中的数据; (3)未命中缓存后,MySQL 通过关键字将 SQL 语句进行解析,并生成一颗对应的解析树,MySQL 解析器将使用
    的头像 发表于 12-12 10:19 194次阅读
    <b class='flag-5'>MySQL</b>执行过程:如何<b class='flag-5'>进行</b>sql <b class='flag-5'>优化</b>