Mysql优化手册

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

前言

SQL优化中就三点:

    • 最大化利用索引
    • 尽可能避免全表扫描
    • 减少无效数据的查询

    一、解各种SQL 的执行频率

    1.1 SHOW STATUS

    show[session|global] status 可以根据需要加上参数“session”或者“global”来显示session 级(当前连接)的统计结果和global 级(自数据库上次启动至今)的统计结果。如果不写,默认使用参数是“session”。

    image.gifimage.gifa1.png

    Com_xxx 表示每个xxx 语句执行的次数,我们通常比较关心的是以下几个统计参数。

      • Com_select:执行select 操作的次数,一次查询只累加1。
      • Com_insert:执行INSERT 操作的次数,对于批量插入的INSERT 操作,只累加一次。
      • Com_update:执行UPDATE 操作的次数。
      • Com_delete:执行DELETE 操作的次数。

      1.2 SHOW PROCESSLIST

      通过该命令来查看当前mysql在进行的线程,

      image.gifa2.png

      1.3 EXPLAIN

      我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。

      image.gifa3.png

      如果id一样,则表示从上而下加载,如果id值不同,则越大表示优先级越高。

      image.gifa4.png

      mysql查看性能工具explain中type有很多种,主要的有:     type的值对优化很重要

      链接类型 说明
      system 表只有一行MyISAM引擎。这是const类型的特例
      const 常量连接,表最多只有一行匹配,通用用于主键或者唯一索引比较时
      eq_ref 每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,特点是使用=,而且索引的所有部分都参与join且索引是主键非空唯一键的索引
      ref 如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键非唯一
      fulltext 全文搜索
      ref_or_null ref类似,但包括NULL
      index_merge 表示出现了索引合并优化(包括交集,并集以及交集之间的并集),但不包括跨表和全文索引。这个比较复杂,目前的理解是合并单表的范围索引扫描(如果成本估算比普通的range要更优的话)
      unique_subquery 在in子查询中,就是value in (select…)把形如select unique_key_column的子查询替换。PS:所以不一定in子句中使用子查询就是低效的!
      index_subquery 同上,但把形如”select non_unique_key_column“的子查询替换
      range 常数值的范围
      index 索引树扫描。a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;d.如单独出现,则是用读索引来代替读行,但不用于查找
      all 全表扫描(full table scan)

      从下到上,越来越好

      二、优化order by 语句

      2.1 mysql中的两种排序方式

        • 通过有序索引顺序扫描直接返回有序数据,不需要额外的排序,操作效率较高。因为索引的结构是B+树,索引中的数据是按照一定顺序进行排列的,所以在排序查询中如果能利用索引,就能避免额外的排序操作。EXPLAIN分析查询时,Extra显示为Using index。
        • Filesort排序,对返回的数据进行排序:所有不是通过索引直接返回排序结果的操作都是Filesort排序,也就是说进行了额外的排序操作。EXPLAIN分析查询时,Extra显示为Using filesort。

        ORDER BY优化的核心原则:尽量减少额外的排序,通过索引直接返回有序数据。

        示例:先查看userinfo表中索引情况

        image.gifa5.png

        order by 优化

        2.2 查询的字段,应该尽可能只包含此次查询使用的索引字段和主键,其余的非索引字段和索引字段作为查询字段则不会使用索引。

        image.gifa6.png

        2.3 排序字段在多个索引中,无法使用索引排序,查询一次只能使用一个索引:

        image.gifa7.png

        所以,只查询索引字段和主键时,可以利用索引来排序。

        MySQL默认的InnoDB引擎在物理上采用聚集索引这种方式,按主键进行搜索,所以InnoDB引擎要求表必须有主键,即使没有显式指定主键,InnoDB引擎也会生成唯一的隐式主键,也就是说索引中必定有主键。

        2.4 排序字段顺序与索引列顺序不一致,无法利用索引排序

        image.gifa8.png

        2.5 ORDER BY排序字段要么全部正序排序,要么全部倒序排序,否则无法利用索引排序。

        image.gifa9.png

        三、优化GROUP BY语句

        3.1 首先看是否有临时表的创建,临时表会使索引失效

          • 如果GROUP BY 的列没有索引,产生临时表
          • 如果GROUP BY时,SELECT的列不止GROUP BY列一个,并且GROUP BY的列不是主键 ,产生临时表
          • 如果GROUP BY的列有索引,ORDER BY的列没索引.产生临时表
          • 如果GROUP BY的列和ORDER BY的列不一样,即使都有索引也会产生临时表
          • 如果GROUP BY或ORDER BY的列不是来自JOIN语句第一个表.会产生临时表
          • 如果DISTINCT 和 ORDER BY的列没有索引,产生临时表

          可以看到这里不仅创建了临时表,还进行了文件排序

          image.gifa10.png

          学习了ORDER BY优化,就知道文件排序效率低,那么可以在这里使用ORDER BY NULL来禁止排序

          image.gifa11.png

          对于不创建临时表的优化可以针对上文例举会产生临时表的情况进行优化。

          四、优化嵌套查询

          子查询有些情况下可以被更有效的连接(JOIN)替代。因为连接(JOIN)不需要再内存中创建临时表来完成

          示例:

          image.gifa12.png

          通过以下sql来查询有角色的用户信息,此时就是通过子查询来完成的

          image.gifa13.png

          看一下执行情况

          image.gifa13.png

          当使用连接来完成上述查询时

          image.gifa14.png

          五、优化OR语句

          对于or语句,如果要利用索引,则or之间的每个条件都必须有索引。并且不走复合索引,必须是单列索引

          首先来看一下userinfo表中的索引情况

          image.gifa15.png

          示例:  此时发现是全表扫描

          image.gifa16.png

          当or的条件是索引时,range指的是有范围的索引扫描,相对于index的全索引扫描

          image.gifa17.png

          优化:使用UNION 来替换OR     type变成了const,而const的效率是远高于range的

          image.gifa18.png

          六、索引提示

          6.1 USE INDEX()

          在你查询语句中表名的后面,添加 USE INDEX 来提供你希望 MySQ 去参考的索引列表,就可以让 MySQL 不再考虑其他可用的索引。

          还是先看一下表中索引情况:一个包括name的复合索引,一个name的单例索引

          image.gifa19.png

          此时查询mysql要判断使用哪个索引

          image.gifa20.png

          当我们在sql中添加use index(), 去给mysql提供参考,注意仅仅是提供参考

          image.gifa21.png

          6.2 IGNORE INDEX()

          和USE INDEX()正好相反,这个是不想用哪个索引,用法是一样的。

          image.gifa22.png

          6.3 FORCE INDEX()

          在查询的时候,数据库系统会自动分析查询语句,并选择一个最合适的索引。但是很多时候,数据库系统的查询优化器并不一定总是能使用最优索引。如果我们知道如何选择索引,可以使用FORCE INDEX强制查询使用指定的索引。

          SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;

          image.gif

          七、模糊查询

          查看表中索引情况,在REALNAME字段上已经创建索引。

          image.gifa24.png

          7.1 尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。

          image.gifa25.png

          image.gifa26.png

          八、尽量不要使用!= 和 <>

          如确实业务需要,使用到不等于符号,需要在重新评估索引建立,避免在此字段上建立索引,改由查询条件中其他索引字段代替。

          image.gifa27.png

          九、隐式类型转换造成不使用索引

          如下SQL语句由于索引对列类型为varchar,但给定的值为数值,涉及隐式类型转换,造成不能正确走索引。

          此时应该加上双引号

          select col1 from table where col_varchar=123;

          image.gif

          十、调整Where字句中的连接顺序

          MySQL采用从左往右,自上而下的顺序解析where子句。根据这个原理,应将过滤数据多的条件往前放,最快速度缩小结果集。

          相关实践学习
          基于CentOS快速搭建LAMP环境
          本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
          全面了解阿里云能为你做什么
          阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
          相关文章
          |
          16天前
          |
          SQL Java 关系型数据库
          MYSQL--JDBC优化
          MYSQL--JDBC优化
          |
          1天前
          |
          存储 关系型数据库 MySQL
          mysql optimizer_switch : 查询优化器优化策略深入解析
          mysql optimizer_switch : 查询优化器优化策略深入解析
          |
          2天前
          |
          关系型数据库 MySQL 数据库
          数据迁移脚本优化过程:从 MySQL 到 Django 模型表
          在大规模的数据迁移过程中,性能问题往往是开发者面临的主要挑战之一。本文将分析一个数据迁移脚本的优化过程,展示如何从 MySQL 数据库迁移数据到 Django 模型表,并探讨优化前后的性能差异。
          |
          3天前
          |
          关系型数据库 MySQL 分布式数据库
          PolarDB产品使用问题之 MySQL数据库中,执行delete命令删除数据后,存储空间通常不会立即释放,该如何优化
          PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
          |
          4天前
          |
          存储 关系型数据库 MySQL
          Mysql优化之索引相关介绍(笔记)
          索引查找从顶层节点开始查找,通过key值,也就是主键的值进行比较,最终定位到存储数据的叶子节点上面,从叶子节点取出响应的数据。
          31 0
          Mysql优化之索引相关介绍(笔记)
          |
          11天前
          |
          SQL 缓存 关系型数据库
          MySQL慢查询优化实践问答
          MySQL慢查询优化实践问答
          |
          15天前
          |
          缓存 关系型数据库 MySQL
          如何优化MySQL 8.0的性能?
          【6月更文挑战第14天】如何优化MySQL 8.0的性能?
          56 5
          |
          13天前
          |
          关系型数据库 MySQL 数据库
          mysql索引优化
          【6月更文挑战第16天】mysql索引优化
          15 2
          |
          17天前
          |
          缓存 监控 关系型数据库
          mysql优化
          【6月更文挑战第12天】mysql优化
          22 3
          |
          22天前
          |
          SQL 关系型数据库 MySQL
          MySQL大数据量分页查询方法及其优化
          MySQL大数据量分页查询方法及其优化