mysql性能分析与优化

Hash索引的限制 

  Hash索引必须进行二次查找

  Hash索引无法用于排序

  Hash索引不支持部分索引查找,也不支持范围查找

  Hash索引中Hash码的计算可能存在Hash冲突

 

为什么要使用索引

  索引大大减少了存储引擎需要扫描的数据量

  索引可以帮助我们进行排序以避免使用临时表

  索引可以把随机I/O变为顺序I/O

 

索引优化策略

  索引列上不能使用表达式或函数

  前缀索引和索引列的选择性,索引的选择性是不重复的索引值和表的记录数的比值

 

联合索引

  如何选择索引列的顺序

  经常会被使用到的列优先

  选择性高的列优先

  宽度小的列优先

 

覆盖索引

  优点:

  可以优化缓存,减少磁盘IO操作

  可以减少随机IO,变随机IO操作变为顺序IO操作

  可以避免对Innodb主键索引的二次查询

  可以避免MyISAM表进行系统调用

  无法使用覆盖索引的情况:

  存储引擎不支持覆盖索引

  查询中使用了太多的列

  使用了双%号的like查询

 

使用索引来优化查询

  使用索引扫描来优化排序

  通过排序操作

  按照索引顺序扫描数据

  索引的列顺序和Order By子句的顺序完全一致

  索引中所有列的方向(升序,降序)和Order by子句完全一致

  Order by中的字段全部在关联表中的第一张表中

 

模拟Hash索引优化查询

  只能处理键值的全值匹配查找

  所使用的Hash函数决定着索引键的大小

 

删除重复和冗余的索引

 

查找未被使用过的索引

 

更新索引统计信息及减少索引碎片

  analyze table table_name

  optimize table table_name 使用不当会导致锁表

 

如何获取由性能问题的sql

  通过用户反馈获取存在性能问题的SQL

  通过慢查日志获取存在性能问题的SQL

  实时获取存在性能问题的SQL

 

使用慢查询日志获取有性能问题的SQL

slow_query_log 启动停止记录慢查日志  set global

slow_query_log_file 指定慢查询日志的存储路径及文件(日志存储和数据存储分开存储)

long_query_time 指定记录慢查日志SQL执行时间的伐值 (记录所有符合条件的SQL)

 

常用的慢查询日志分析工具 (mysqldumpslow)

  汇总除查询条件外其他完全相同的sql,并将分析结果按照参数中所指定的顺序输出

  mysqldumpslow -s r -t 10 slow-mysql.log

  -s order(c,t,l,t,at,al,ar) 指定按哪种排序方式输出结果

  c :总次数

  t :总时间

  l :锁的时间

  r :总数据行

  at,al,ar:t,l,r平均数

  

  -t top 指定取前几条作为结束输出

  

 

常用的慢查日志分析工具(pt-query-digest)

  pt-query-digest \

  --explain h=127.0.0.1,u=root,p=p@ssWord \

  slow-mysql.log

 

查询速度为什么会慢?

  客户端发送sql语句给服务器

  服务器检查是否可以在查询缓存中命中该sql

  服务器端进行sql解析,预处理,再由优化器生成对应的执行计划

  根据执行计划,调用存储引擎API来查询数据

  将结果返回给客户端

 

查询缓存对sql性能的影响

  优先检查这个查询是否命中查询缓存中的数据

  通过一个对大小写敏感的哈希查找实现的

  对于一个读写频繁的系统使用查询缓存很可能会降低查询处理的效率

  所以在这种情况下建议不要使用查询缓存

 query_cache_type 设置查询缓存是否可用

  DEMAND 表示只有在查询语句中使用SQL_CACHE和SQL_NO_CACHE来控制是否需要缓存

 query_cache_size 设置查询缓存的内存大小

 query_cache_limit 设置查询缓存可用存储的最大值

    加上SQL_NO_CACHE可以提高效率

 query_cache_wlock_invalidate 设置数据表被锁后是否返回缓存中的数据

query_cache_min_res_unit 设置查询缓存分配的内存块最小单位

 

MySQL 依照这个执行计划和存储i 引擎进行交互

  这个阶段包括了多个子过程:

    解析SQL,预处理,优化SQL执行计划

    语法解析阶段是通过关键字对MySQL语句进行解析,并生成一颗对应的“解析树”

    MySQL解析器将使用MySQL语法规则验证和解析查询

    包括检查语法是否使用了正确的关键字

    关键字的顺序是否正确等

    预处理阶段是根据MySQL规则进一步检查解析树是否合法

    检查查询中所涉及的表和数据列是否存在及名字或别名是否存在歧义等等

    语法检查全都通过了,查询优化器就可以生成查询计划了 

 

SQL的解析预处理及生成执行计划

  会造成MySQL生成错误的执行计划的原因

    统计信息不准确

    执行计划中的成本估算不等同于实际的执行计划的成本(MySQL服务器层并不知道哪些页面在内存中   哪些页面在磁盘上  哪些需要顺序读取  哪些要页面随机读取)

    MySQL优化器所认为的最优可能与你所认为的最优不一样(基于其成本模型选择最优的执行计划)

    MySql 不会考虑不受其控制的成本(存储过程,用户自定义的函数)

 

MySQL优化器可优化的SQL类型

  重新定义表的关联顺序(优化器会根据统计信息来决定表的关联顺序)

  将外连接转化成内链接 (where条件和库表结构等)

  使用等价变换规则(5=5 and a>5)将被改写为a>5

  优化count() ,min()和max()  (select tables optimized away 优化器已经从执行计划中移除了该表,并以一个常数取而代之)

  讲一个表达式转化为常数表达式

  子查询优化 (子查询转换为关联查询)

  提前终止查询

  对in()条件进行优化

 

 

如何确定查询处理各个阶段所消耗的时间

  使用profile

    减少查询所消耗的时间,加快查询的相应速度

  set profiling =1 ;

  启动profile ,这是一个session级的配置

 

  执行查询

  show profiles;  查看每一个查询所消耗的总时间的信息

  show profile for query N;  查询的每个阶段所消耗的时间

 

如何确定查询处理各个阶段所消耗的时间

使用performance_schema

  update `setup_instruments` set enabled = ' YES',TIMED='YES' WHERE NAME LIKE 'stage%';

 

  UPDATE setup_consumers SET enabled='YES' WHERE NAME LIKE 'events%';

 

 

大表的数据修改最好要分批处理

  1000万行记录的表中删除/更新100万行记录一次只删除/更新5000行记录,暂停几秒

 

  

 

特定的sql的查询优化

  如何修改大表的表结构

  pt-online-schema-change \

  --alter = "MODIFY c VARCHAR(150) NOT NULL DEFAULT '' " \

  --user=root --password=Password D=databaseName,t=tableName \

  --charset=utf8 --execute

 

 

  

posted @ 2018-03-21 15:19  jintaonote  阅读(109)  评论(0编辑  收藏  举报