影响MySQL性能的相关因素

mysql 性能优化
创建于:2019年08月29日 更新于:2019年10月17日

笔记整理自《MySql性能调优与架构设计》

商业需求对性能的影响

1.不合理的需求造成资源投入大,实际收益低
例如一个论坛网站,实时更新帖子数量、统计用户在线数。
在很多应用系统中,实时和准实时,精确与基本准确,在很多地方所带来的性能消耗可能是几个性能的差别。在系统性能优化中,应该尽量分析出哪些可以不实时和不完全精确,并作出一些相应的调整,这会给大家带来意想不到的巨大性能提升

2.无用功能堆积使系统过度复杂,影响整体性能
很多时候,为系统增加某个功能可能并不须要花费太多的成本,而要想将一个已经运行了一段时间的功能从原有系统中撤下来却是非常困难的。随着时间的积累,应用系统会越来越复杂,不仅维护困难,性能也会越来越差。尤其是有些并不合理的功能,在设计之初或是刚上线的时候由于数据量较小,不会带来多少性能损耗。可随着时间的推移,数据库中的数据量越来越大,数据检索越来越困难,整个系统带来的资源消耗也就越来越大。

系统架构及实现对性能的影响

1.数据库存放的数据是否合理
数据库是一个操作方便的存储中心,以至于什么数据都往里面存储,最终导致性能低下,资源浪费。
以下几类数据都不适合存放在数据库中:

  1. 二进制多媒体数据
  2. 流水队列数据
  3. 超大文本数据

2.是否合理地利用了应用层Cache机制
可以把很少变化的活跃数据通过应用层的Cache机制缓存到内存中。
以下数据适合通过Cache机制来提高系统性能:

  1. 系统各种配置及规则数据
  2. 活跃用户的信息数据
  3. 基于时间段的统计数据
  4. 其他一些访问频繁但变更较少的数据

3.数据层实现都是最精简的吗
例如此博客文章表有个分类ID字段,对应一张分类表。列表页获取每篇文章分类名称的时候有两种方法。

  1. 把查询出来的文章遍历,在循环里根据分类ID查询分类表获取对应的分类名称
    (1)获取文章列表
    “select id, title, catetory_id from article limit 10”;
    (2)遍历查询出来的结果,在循环里查询10次
    “select name from category where id = ?”

  2. 查询出来文章列表后,获取所有分类ID,根据分类ID使用in进行查询
    (1)获取文章列表
    “select id, title, catetory_id from article limit 10”;
    (2)获取所以分类ID,使用in进行查询

    // PHP代码:
    $categoryId = implode(',', array_column($list, 'category_id')); // 使用文章列表$list,获取所有分类ID
    "select id,name from category where id in ({$categoryId})";
    

    很明显第二种解决方案优于第一种

4.重复执行相同功能的Query造成资源浪费
例如:该博客详情页左侧有同一分类下的所有文章列表。
在每篇博文的最下方还显示该文章分类下的上一篇和下一篇。
如果在查询出了左侧所有文章后,上一篇和下一篇仍然使用数据库查询,那就会造成资源浪费

Query语句对系统性能的影响

  1. 在索引列进行数学运算和函数运算
  2. 在低基数列上建立索引,例如‘性别’
    有的时候进行全表浏览要比必须读取索引和数据表更快,尤其是当索引包含的是平均分布的数据集更是如此
  3. 使用%前导的查询,例如like ‘%xxx’
    无法使用索引,导致全表扫描
    ……
    具体SQL优化将在后续文章介绍

Schema设计对系统的性能影响

  1. 一个表太多的列,过分反范式
  2. 太多表关联.过分范式化
  3. 使用外键保持数据一致性
    外键会导致父表和子表之间耦合,十分影响SQL性能,出现过多的锁等待,甚至造成死锁
  4. 表没有主键
  5. 使用分区表
    使用分区表查询的字段必须是分区键,否则会遍历所有的分区表,并不会带来性能上的提升。此外分区表在物理结构上仍旧是一张表,此时我们更改表结构,一样不会带来性能上的提升。所以应采用切表的形式做拆分,如程序上需要对历史数据做查询,可通过union all的方式关联查询。另外随着时间的推移,历史数据表不再需要,只需要在从库上dump出来,即便捷地迁移至备份机
  6. 字段定义为NULL
    NULL值很难进行查询优化,它会使索引统计更加复杂,还需要mysql内部进行特殊处理
  7. 数据量大、经常查询的表不设置索引
    ……
    具体数据库设计优化将在后续文章介绍

硬件环境对系统性能的影响

对各种类型的应用做一个简单的分析,再针对性地给出这三类部件的基本选型建议。

  1. 对于并发量大,整体数据量比较多,但每次访问的数据比较少,且访问的数据比较离散,活跃数据占总体数据的比例不是太大的应用
    (1)扩大内存容量,尽可能多的将活跃数据缓存(Cache)到内存中;
    (2)IO访问非常频繁,所以磁盘存储的要求是IOPS表现要很好,吞吐量是次要因素;
    (3)CPU处理能力需要比较强劲;
    (4)网络交互非常频繁,所以主机与客户端交互的网络设备对流量能力要好。

  2. 对于数据量非常大,并发访问不多,但每次访问须要检索的数据量都比较多,而且数据访问相对较为集中,没有太明显活跃数据的应用
    (1)磁盘存储系统的单位容量应尽量大
    (2)IO系统的性能要求是要有尽可能大的每秒IO吞吐量,所以应该选用相应的磁盘;
    (3)并发请求较少,所以对CPU处理能力没有太苛刻的要求;
    (4)对客户端交互的网络设备要求并不是太高

  3. 对于数据量不是特别大,但是访问请求极其频繁,而且大部分是读请求。可能每秒须要提供上万甚至几万次请求。每次请求返回的记录较少的应用
    (1)需要较大的内存来Cache住大部分的数据,这能够保证非常高的命中率;
    (2)磁盘IO量比较小,所以磁盘也不需要特别高性能的;
    (3)并发请求非常频繁,必须要较强的CPU处理能力才能处理;
    (4)交互的数据较少,一般来说普通的千兆网卡已经足够了