Mysql学习(调优篇)

影响mysql的性能因素

  • 业务需求对Mysql的影响

  • 存储定位对Mysql的影响

           系统各种配置和规则数据

           活跃用户的基本信息数据,个性化定制信息数据

          准实时的统计信息数据

          其他一些访问频繁但变更较少的数据

         二进制多媒体数据

         流水队列数据

         超大文本数据

         不适合放进mysql的数据

         需要放进缓存的数据

  • Schema设计对系统的性能影响

          尽量减少对数据库访问的请求

         尽量坚守无用数据的查询请求

性能分析

1.mysql有专门负责优化select语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供它认为最优的执行计划(它认为最有的数据检索方式,但不见的是DBA认为是最优的,这部分最耗费时间)

2.当客户端向mysql请求一条Query,命令解释器模块完成请求分类,区别出是select并转发给Mysql query optimizer时,Mysql query optimizer 首先会对整条Query进行优化,处理掉一些常量表达式的预算,直接换算成常量值,并对Query中的查询条件进行简化和转换,如去掉一些无用或者显而易见的条件,结构调整等,然后分析Query中的Hint信息(如果有),看显示Hint信息是否可以完全确定该Qery的执行计划,如果没有Hint或者Hint信息还不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query近行写相应的计算分析,然后再得处最后的执行计划。

 Mysql常见瓶颈

  • CPU:CPU在包和的时候一般发生在数据装入内存或从磁盘读取数据时候
  • IO:磁盘I/O平静发生在装入数据远大于内存容量的时候
  • 服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态

性能下降SQL慢 执行时间长 等待时间长 原因分析

  • 查询语句写的烂
  • 索引失效(单值,复合)
  • 关联查询太多join
  • 服务器调优鸡各个参数设置(缓冲,线程数)

MySQL常用性能分析手段

在优化mysql时,需要哦通过对数据库进行分析,常见的分析手段有慢查询日志,EXPLAIN分析查询,profiling分析,以及show命令查询系统状态及系统变量,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。

性能瓶颈定位

Mysql> show status ——显示状态信息(扩展show status like ‘XXX’)

Mysql> show variables ——显示系统变量(扩展show variables like ‘XXX’)

Mysql> show innodb status ——显示InnoDB存储引擎的状态

Mysql> show processlist ——查看当前SQL执行,包括执行状态、是否锁表等

Shell> mysqladmin variables -u username -p password——显示系统变量

Shell> mysqladmin extended-status -u username -p password——显示状态信息

Explain(执行计划)

是什么:使用E关键字可以模拟优化器执行sql查询语句,从而知道Mysql是如何处理你的sql语句的,分析你的拆线呢语句或是表结构的性能瓶颈

能干吗:

  • 表的读取顺序
  • 数据读取操作的操作类型
  • 哪些索引被实际使用
  • 表之间的引用
  • 每张表有多少行被优化器查询

怎么玩:

  • Explain+SQL语句
  • 执行计划包含的信息(如果有哦分区表的话还有partitions)

  1. id(select查询的序列号,包含一组数据,表示查询中执行select子句或操作表的顺序)
  • id相同,执行顺序从上往下
  • id全不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
  • id部分相同,执行顺序是先按照数字大的限制性,然后数字相同的按照从上往下的顺序执行

 2.select_type(查询类型,用于区别普通查询,联合查询,子查询等复杂查询)

  • simple:简单的slelect查询,查询中不包含子查询或者union
  • primary:查询中若包含任何复杂的子部分,最外层查询被标记为PRIMARY
  • SUBQUERY:在select或where列表中包含了子查询
  • DERIVED:在from列表中包含的子查询被标记为DERIVED,mysql会递归执行这些查询,把结果放在临时表中
  • UNION:若第二个select出现Union之后,则被标记为UNION,若UNION包含在from子句的资产寻中,外层select将被标记为DERIVED
  • union result:从UNION表获取结果的select

3.table 显示这一行的数据是关于哪张表的

4.type(显示查询使用了哪种类型,从最好到最差依次排列 system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>All)

一般来说得保证拆线呢至少达到range级别,最好达到ref

  • system:表只有一行记录,是const类型特例,平时不会出现
  • const:表示通过索引一次就能找到,const用于比较primary key 或 unique索引,因为只要匹配一行数据,所以很快,如果将主键置于where列表中,mysql就能将该查询转换为一个常量
  • eq_ref:唯一索引扫描,对于每个索引值,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
  • ref:非唯一索引扫描,范围匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值得行,然而,它可能也会找到多个符合条件得行,所以他应该属于查找和扫描得混合体
  • range:只检索给定范围得行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是你得where语句中出现了between,<,>,in等查询,这种范围扫描索引比全表扫描要好,因为它只需开始于索引得某一点,而结束于另一点,不用扫描全部索引。
  • index:full index scan,index于ALL去表为index类型只遍历索引树,通常比All块,因为索引文件通常比数据文件小(也就是说虽然all和index都读全表,但index是从索引中读取得,而all是从硬盘读得)
  • All 将遍历全表找到匹配得行

5.possible_keys(显示可能应邀在这涨表得索引,一个或多个,查询涉及到得字段若存在索引,则该索引将被列出,但不一定被查询实际使用)

6.key 实际使用得索引,如果为null,则没有使用索引,查询中若使用了覆盖索引,则该索引和查询得selelct字重叠,仅出现在key列表中

7.key_len

表示索引中使用得字节数,可通过该列计算查询中使用得索引得长度。在不损失精确性得情况下,长度越短越好。

key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表i当以计算而得,不是通过表内检索出的

8.ref (显示索引的哪一列被使用了,如果可能的话,是一个常数,哪些列或常量被用于查找索引列上的值)

9.rows(根据表统计统计信息及选用情况,大致估算找到所需的记录需要读取的行数)

10.Extra 包含不适合在其他列中显示但十分重要的额外信息

  • using filesort:说明mysql会对数据使用一个外部的索引排序,不是按照表内的索引顺序进行读取的,mysql中无法利用索引完成的排序操作称为“文件排序”.常见于order by 和 group by。
  • Using temporary 使用了临时表保存中间结果,mysql在对查询结果排序时使用临时表,常见于排序order by 和分组查询group by。
  • using index :表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错,如果哦同时出现了using where,表明索引被用来执行索引键值的查找:否则索引被用来读取数据而非执行查找操作
  • using where:使用了where过滤
  • using join buffer:使用了连接缓存
  • impossible where:where 子句的值总是false,不能用来获取任何元组。
  • select tables optimized away:在没有 group by子句的情况下,基于索引优化操作或对于MyISAM存储引擎优化Count(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化
  • distinct:优化distinct操作,再找到第一匹配的元组后即停止找同样值的动作

例子

1.第一行(执行顺序4):id列为1 ,表示时union里面得第一个select select_type列为Primary表示该查询为外层查询,table列查询结果来自一个衍生表,其中deriverd3中3代表该查询衍生自第三个slecet查询,即id为3的select。

2.第二行(执行顺序2):id为3,是整个查询中第三个select的一部分,因查询包含在from中,所以为derived

3.第三行(执行顺序3):select 列表中的子查询select_type为subquery。为整个查询中的第二个select

4第四行(执行顺序1):select_type为union,说明第四个select是union里面的第二个select(select name,id from t2)

5.第五行(执行顺序5):代表从union的临时表中读取行的阶段,table列的<union1,4>表示用第一个和第四select的结果进行union操作。

慢查询日志

mysql的慢查询日志是mysql提供的一种日志记录,它用来记录在mysql中相应时间超过阈值的语句,具体指运行时间超过long_query_time值得sql,则会被记录到慢查询日志中

  • long_query_time得默认值为10 ,意思是运行10s以上得语句
  • 默认情况下,Mysql数据库没有开启慢查询日志,需要手动设置参数开启

查看开启状态

show variables like '%slow_query_log%'

开启慢查询日志:

  • 临时配置:
set global slow_query_log ='on'

set global slow _query_log_file='/var/lib/mysql/hostname-slow.log';

set global log_query_time = 2

使用set操作开启慢查询日志只对当前数据库生效,如果MySQL重启则会失效。

  • 永久配置

修改配置文件my.cnf或my.ini,在[mysqld]一行下面加入两个配置参数

[mysqld]
slow_query_log = ON
slow_query_log_file = /var/lib/mysql/hostname-slow.log
long_query_time = 3

注:log-slow-queries 参数为慢查询日志存放的位置,一般这个目录要有 MySQL 的运行帐号的可写权限,一般都将这个目录设置为 MySQL 的数据存放目录;long_query_time=2 中的 2 表示查询超过两秒才记录;在my.cnf或者 my.ini 中添加 log-queries-not-using-indexes 参数,表示记录下没有使用索引的查询。

  • 得到返回记录集最多的10个SQL

    mysqldumpslow -s r -t 10 /var/lib/mysql/hostname-slow.log

  • 得到访问次数最多的10个SQL

    mysqldumpslow -s c -t 10 /var/lib/mysql/hostname-slow.log

  • 得到按照时间排序的前10条里面含有左连接的查询语句

    mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/hostname-slow.log

  • 也可以和管道配合使用

    mysqldumpslow -s r -t 10 /var/lib/mysql/hostname-slow.log | more

也可使用 pt-query-digest 分析 RDS MySQL 慢查询日志

索引优化

  1. 全值匹配我最爱
  2. 最佳做前缀法则,比如建立了一个联合索引(a,b,c),那么其实我们可利用的索引就有 a,ab,abc
  3. 不在索引列上做任何操作(计算,函数,自动or手动类型转化),会导致苏哦因失效而转向全表扫描
  4. 存储引擎不能使用索引中范围条件的右边的列
  5. 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致))减少select
  6. is null ,is not null 也无法使用索引
  7. like “xxx%”是可以使用索引的, like“%xxxx”则不行,会变成全表扫描
  8. 字符串不加单引号索引会失效
  9. 少用or,用它来连接时会索引失效
  10. <,<=,=,>,>=,BETWEEN,IN 可用到索引,<>,not in ,!= 则不行,会导致全表扫描

一般性建议

  • 对于单键索引,尽量选择针对当前query过滤性更好的索引

  • 在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

  • 在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引

  • 尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

  • 少用Hint强制索引

查询优化

永远小表驱动大表

当B表的数据集必须小于A表的数据集时,用in优于exists

猜你喜欢

转载自blog.csdn.net/Chen_leilei/article/details/112534487