读《高性能mysql》笔记

性能监控工具

  • sysbench
  • pt-query-digest
  • Anemometer
  • new rilic
  • xhprof生产环境下的PHP性能跟踪工具
  • show profile
  • show status

选择正确的数据类型

  • 通常越小越好
  • 越简单越好
  • 采用not null
  • 使用枚举类型
  • TIMESTAMP通常优于DATETIME
  • 多表关联,关联主键数据类型应当一致
  • 不要怕用NULL,避免不存在的值,如:DATETIME NOT NULL DEFAULT ‘0000-00-00 00:00:00’
  • 在冗余量允许的情况下,减少JOIN,考虑适当把同一个字段数据存到不同表里,使用触发器来维护,这可以减少全表扫描。

建立合适的索引

  • 避免随机I/O
  • 索引的选择性
  • 对于联合索引,mysql只能高效利用最左前的字段,所以索引字段顺序很重要,
  • B-Tree结构的索引,是按顺序存储索引key和数据指针的,如果索引key字符数较多,这会使索引很大。
  • 可以对索引数据进行hash,用数据的hash来索引数据。使用触发器进行维护。
  • “独立的列”,应当把索引单独放在比较符号的一侧,mysql才能利用其索引来。
  • 前缀索引,对于长字段,可以只索引字段前缀部分,如host(10)
  • Innodb使用的聚簇索引,按主键顺序连续存储数据和索引。
  • 覆盖索引,索引本身含有查询所需的全部数据。
  • MyISAM按插入顺序存储数据,每行定长,这在查询的时候可以直接跳过
  • Mysql5.6可以推送索引条件到存储引擎层
  • 冗余索引,对于(A,B)来说要查询B,(A)是冗余索引,(B),(B,A)则不是
  • 对于mysql查询,mysql可以利用第一个范围查询之前所有列的最左前索引
  • 技巧,使用闭合条件来优化查询,如:有一个索引INDEX(‘sex’,‘country’,‘age’),如何我们要查询所中国26岁的用户,country并不是最左前字段,利用不了这个索引,我们可以用闭合条件,SEX IN(‘男’,‘女’),跳过sex字段,使用这个索引。
  • 延迟关联,在查询一个大列表的冷数据时,可能会使用limit 1000000,10 这样的,这对Mysql来说,他需要扫描并丢弃前1000000行。我们可以先只查询出主键id,再根据主键id查询对应数据,可以减少系统传输的数据量,减少I/O开销
  • 避免单行查找,即使是单行查找,系统也会有很多准备工作。

查询优化

  • mysql的处理流程是,先取一个大的结果集,慢慢丢弃不需要的结果。理解这个流程,可以预想到一个SQL,mysql会怎样处理。
  • 联表查询会返回全部列
  • 分解关联查询,可以提高缓存命中率,减少锁,提高程序拓展性。
  • 避免IN()一个结果集,如where a.id IN(select id from…),改成inner join
  • 没有万能经验,子查询和join性能可以多实测
  • mysql通过嵌套循环来实现查询,即使是一条简单select
  • 大数据量的limit优化,其实对于多数应用,列表数据是允许少量冗余的,可以考虑传入上一页的最后一个主键id作为定位条件,不用limit准确的偏移。

Mysql高级特性

  • 分区表
  • 视图(虚拟表)
  • 外键约束