MySQL性能调优与架构设计-笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t1g2q3/article/details/85458880
  • MySQL的主要适用场景
    • ①Web网站系统:免费开源、安装配置简单。
    • ②日志记录系统:MyISAM实现高性能插入和查询。
    • ③数据仓库系统:免费支持主从复制。
  • InnoDB存储引擎的特点:
    • a. 支持事务安全
      • InnoDB是一个事务安全的存储引擎,其事务安全性主要就是通过在线redo日志和记录在表空间中的undo信息来保证的。redo日志中记录了InnoDB所做的所有物理变更的事务信息,通过redo日志和undo信息,InnoDB保证了在任何情况下的事务安全性。
    • b. 数据多版本读取
    • c. 支持行锁(通过索引来完成的)(适合用于高并发场景)
    • d. 支持外键
  • 影响性能的相关因素
    • 1、需求是否合理
    • 2、数据类别(二进制多媒体数据、流水队列数据->用第三方队列软件、超大文本数据)
    • 3、缓存是否有效
    • 4、准实时数据和实时数据
    • 5、过度依赖Query语句
    • 6、重复查询
  • MyISAM的锁定机制完全是由MySQL提供的表级锁定实现的。
  • InnoDB的锁定机制
    • InnoDB的锁定是通过在需要锁定的某行记录的第一个索引键之前和最后一个索引键之后的空域空间标记锁定信息实现的。InnoDB的这种锁定实现方式被称为“NEXT-KEY locking”(间隙锁),因为Query在执行过程中通过范围查找,它会锁定整个返回内所有的索引键值,即使这个键值并不存在。
  • 除了间隙锁给InnoDB带来的负面影响,通过索引实现锁定的方式还存在其他几个较大的性能隐患
    • a. 当Query无法利用索引的时候,InnoDB会放弃使用行级别锁定而改用表级别锁定,造成并发性能降低。
    • b. 当Query使用的索引并不包含所有过滤条件时,数据检索使用到的索引键中的数据可能有部分并不属于该Query的结果集行列,但是也会被锁定,因为间隙锁锁定的是一个范围,而不是具体的索引键。
    • c. 当Query在使用索引定位数据的时候,如果使用的索引键一样单访问的数据行不同(索引只是过滤条件的一部分),它们一样会被锁定。
  • InnodDB行锁、表锁、间隙锁、死锁、使用共同索引不同数据的阻塞
  • InnoDB行锁优化
    • a. 尽可能让所有的数据检索都通过索引完成,避免InnoDB无法通过索引键加锁而升级为表级锁定。
    • b. 合理设计索引,让InnoDB在索引键上面加锁的时候尽可能准确,尽可能的缩小锁定范围,避免不必要的锁定。
    • c. 尽量减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录。
    • d. 尽量控制事务的大小,减少锁定的资源量和锁定时间长度。
    • e. 在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少因为实现事务隔离级别带来的附加成本。
  • 由于InnoDB的行锁和事务性,所以肯定会产生死锁,常用的减少死锁产生概率的建议
    • a. 类似业务模块中,尽可能按照相同的访问顺序来访问,防止产生死锁。
    • b. 在同一个事物中,尽可能做到一次锁定所有需要的资源,减少死锁产生的概率。
    • c. 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死多产生的概率。
  • Query语句优化思路
    • a. 优化更需要优化的Query(高并发的Query)
    • b. 定位优化对象的性能瓶颈(判断Query的瓶颈是IO还是CPU)
    • c. 明确的优化目标
    • d. 从Explain入手
    • e. 多使用profile
    • f. 永远使用小结果集驱动大结果集、
    • g. 尽可能在索引中完成排序
    • h. 只取出自己需要的Columns
    • i. 仅仅使用最有效的过滤条件
    • j. 尽可能避免复杂的Join和子查询
  • profile判断Query性能瓶颈是IO还是CPU
    • set profiling=1;
    • 执行查询;
    • show profiles;查看queryId
    • shwo profile cpu , block for quuery queryId;、
  • 分析是否需要创建索引
    • a. 频繁最为查询条件的字段应该创建索引
    • b. 唯一性太差的字段不适合单独创建索引,即使创建了,系统也可能不会使用
    • c. 更新非常频繁的字段不适合创建索引
    • d. 不会出现在where子句中的字段不需要创建索引
  • MySQL中索引的限制
    • a. MySQL目前不支持函数索引
    • b. 使用不等于的时候MySQL无法使用索引
    • c. 过滤字段使用了函数运算后M有SQL无法使用索引
    • d. Join语句中Join条件字段类型不一致的时候MySQL无法使用索引
    • f. 使用like等操作的时候如果条件以通配符%开始MySQL无法使用索引
    • g. 使用非等值查询的时候MySQL无法使用Hash索引
  • Join的实现原理和优化思路
    • 实现原理:Nested Loop Join
    • 优化思路:小结果集驱动大结果集或者避免Join连接查询
  • Order By优化
    • MySQL中Order By的实现由两种类型:
      • a. 通过有序索引而直接取得有序的数据,不用进行任何排序操作即可得到满足客户端要求的有序数据。
      • b. 通过MySQL的排序算法将存储引擎中返回的数据进行排序然后再将排序后的数据返回给客户端
  • Group By优化
    • MySQL中Group By的实现有三种方式:
      • a. 使用松散(Loose)索引扫描实现Group By
      • 实际上就是完全利用索引扫描来实现Group By,不需要扫描所有满足条件的索引键即可完成操作得出结果,用Explain分析可以看到 Using index for group-by
      • 要使用松散索引扫描需要满足以下几个条件:
        • ♦ Group By条件字段必须在同一个索引中最前面的连续位置
        • ♦ 在使用Group By的同时,只能使用Max和Min这两个聚合函数
        • ♦ 如果引用到了该索引中Group By条件之外的条件字段的时候,必须以常量形式存在
      • b. 使用紧凑索引扫描实现Group By
        • 在MySQL 中,MySQL Query Optimizer 首先会选择尝试通过松散索引扫描来实现GROUP BY 操作,当发现某些情况无法满足松散索引扫描实现GROUP BY 的要求之后,才会尝试通过紧凑索引扫描来实现。当GROUP BY 条件字段并不连续或者不是索引前缀部分的时候,MySQL Query Optimizer 无法使用松散索引扫描,设置无法直接通过索引完成GROUP BY 操作,因为缺失的索引键信息无法得到。但是,如果Query 语句中存在一个常量值来引用缺失的索引键,则可以使用紧凑索引扫描完成GROUP BY 操作,因为常量填充了搜索关键字中的“差距”,可以形成完整的索引前缀。这些索引前缀可以用于索引查找。而如果需要排序GROUP BY 结果,并且能够形成索引前缀的搜索关键字,MySQL 还可以避免额外的排序操作,因为使用有顺序的索引的前缀进行搜索已经按顺序检索到了所有关键字。
      • c. 使用临时表实现Group By
    • 在优化GROUP BY 的时候还有一个小技巧可以让我们在有些无法利用到索引的情况下避免filesort 操作,也就是在整个语句最后添加一个以NULL排序(ORDER BY NULL)的子句。

猜你喜欢

转载自blog.csdn.net/t1g2q3/article/details/85458880
今日推荐