高性能MySQL优化要点整合

本篇文章为《高性能MySQL》一书的读书笔记,主要提取了几点在开发中会用到的高性能的做法与一些MySQL的介绍

1. MySQL架构

MySQL最重要、最与众不同的特性是它的存储引擎架构。这种架构的设计将查询处理及其他系统任务和数据的存储/提取相分离。此时可以根据性能、特性以及其他需求来定制化数据存储的方式(存储引擎)

1.1 MySQL逻辑架构

在这里插入图片描述

服务器逻辑架构图,截取自《高性能MySQL》

  • 中间那层架构为MySQL核心部分,负责查询解析、分析、优化、缓存以及内置函数(日期、时间、数学等),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等
  • 最下面一层存储引擎层负责数据的存储和提取,每个存储引擎都有各自的优势和劣势。服务器通过API与存储引擎进行通信。存储引擎API包含了几十个底层函数,用于执行诸如“开始一个事务”等操作。存储引擎不会去解析SQL,只是简单的响应上层服务器的请求

2. Schema与数据类型优化

应该根据系统将要执行的查询语句来设计schema,需要权衡各种因素。例如反泛式的设计可以加快某些查询,但可能使另一个查询变慢。

2.1 数据类型的选择

2.1.1 整数类型

INT(1) 和 INT(20) 在存储与计算上是相同的,只不过其规定了显示字符的个数

存储整数,有如下类型(包括类型所占的存储空间,间接代表了其值的范围)

  • TINYINT(8 bit)
  • SMALLINT(16 bit)
  • MEDIUMINT(24 bit)
  • INT(32 bit)
  • BIGINT(64 bit)

整数类型有可选的UNSIGNED属性,表示无符号,如无符号则存储的值范围扩大一倍(乘2)

2.1.2 字符串类型

VARCHAR

用于存储可变长字符串,需要多消耗1到2的额外字节来存储字符串(记录长度),节省了存储空间,对性能有帮助,但是如果UPDATE使得行变得比之前更长,InnoDB需要分裂页来使行可以放入页内,造成一定的碎片化

下面情况使用VARCHAR是合适的:

  • 字符串列的最大长度比平均长度大很多,充分发挥了变长字符串的节省能力
  • 列的更新很少,这样碎片化就少了
CHAR

MySQL总是根据定义的字符串长度分配空间。对于固定的列,存储空间也比VARCHAR小1到2个字节(记录长度)

下面情况使用CHAR是合适的:

  • MD5值,固定的长度,更少的存储空间
  • 很短的字符串,或者所有值都接近同一个长度
  • 经常变更的值,不易产生碎片

VARCHAR(5) 和 VARCHAR(200) 存储的空间开销是一样的,但更长的列会消耗更多的内存(或磁盘),体现在使用内存临时表(或磁盘临时表)进行排序或操作时。

BLOB和TEXT

为存储很大的数据而设计的字符串数据类型

  • MySQL把这两个当作一个独立的对象处理,如果太大,InnoDB会使用专门的外部存储区域来进行存储,此时每个值在行内就存储1-4个字节的指针
  • 两者的不同是BLOB存储的是二进制数据,没有排序规则和字符集,而TEXT有
  • 不能将这两列全部长度进行索引,进而没有覆盖索引和索引消除的排序
使用枚举代替字符串类型

枚举列把一些不重复的字符串存储成一个预定义的集合,MySQL在存储枚举时非常紧凑,会根据列表值的数量压缩到一到两个字节中。

  • MySQL在内部会将每个值在列表中的位置保存为整数,并且在.frm文件中保存数字-字符串的映射关系(查找表),所以在查找时有一些开销,在其与CHAR/VARCHAR列关联时体现,所以有与字符串类型做关联时最好使用字符串(或者枚举与枚举进行关联,会更加的快)
    • 有时候枚举会大大减少表的大小,所以有时候关联的开销也是值得的
  • 缺点是字符串列表是固定的,添加元素只能在列表末尾添加

2.1.3 日期和时间类型

DATATIME

保存大范围的值,从1001年到9999年,精度为秒,格式为YYYYMMDDHHMMSS的整数,使用8个字节的存储空间

TIMESTAMP

时间戳,保存了从1970年1月1日以来的秒数,与UNIX时间戳相同,只使用4个字节的存储空间,只能表示1970到2038年

2.1.4 位数据类型

少数几种存储类型使用紧凑的位存储数据,底层来讲都是字符串类型

BIT

在InnoDB中,为每个BIT列使用一个足够存储的最小整数类型来存放,所以其在InnoDB中不能节省空间,并且结果有时可能令人费解(存储的二进制查找出来的是字符码对应的字符串,例如57的二进制,查找出来会变为"9"),应该谨慎使用BIT类型,如果存储一个true/false值,可以使用CHAR类型,节省了空间又不会令人费解

SET

通过一系列打包的位集合,可以保存很多个true/false的值,有效利用存储空间,例如一条记录里有一列权限,其中有是否可读,是否可写,是否可删除,一系列的是否,通过指定位的0/1来达到

2.1.5 选择标识符

标识符即为一行数据中唯一标识此行的列,需要确保所有关联表中的此标识符都使用同样的类型,包括UNSIGNED这样的属性

  • 整数类型
    • 通常是标识列的最好选择,它们很快并且可以使用AUTO_INCREMENT
  • ENUM和SET
    • 糟糕的选择,此类型是固化的视图,如果确定表主键只有固定那么几个的话,也可以选择
  • 字符串类型
    • 应该避免使用字符串类型作为标识列,它们很消耗空间,通常比数字类型慢
    • 多加注意“随机”的字符串,如MD5、SHA1、UUID等等
      • 插入时会随机写索引的不同位置,使得INSERT更慢,导致页分裂、磁盘随机访问
      • SELECT更慢,因为逻辑相邻的列分布在物理地址的不同位置

2.2 MySQL的schema设计

2.2.1 范式与反范式

范式化的优点:

  • 更新操作比反范式快,没有冗余数据,只需要修改最少的数据
  • 范式化的表通常更小,可以更好的放入内存,执行操作更快
  • 几乎没有冗余数据代表着更少的DISTINCT或者GROUP BY语句

范式化的缺点:

  • 查询时通常需要关联表,才能拿到一个完整需要的数据信息
  • 有时候不同列在不同的表中,原本这些列只需要利用一次索引就可以完成查询

反范式化的优点:

  • 所有数据都在一张表中,避免了关联操作,如果不需要关联表,最差情况下(全表扫描),当数据量比内存大时可能比关联快得多,因为是顺序IO
  • 在一些查询中,使用一个索引就能得到所有的列,有些查询得益于此变得比关联快得多

反范式化的缺点:

  • 列数据冗余存储,更新数据时可能需要更新多表,更新变慢变复杂
  • 行信息不明确,例如用户表与用户发送的消息表合并在一起,通常是很糟糕的

2.2.2 混用范式化与反范式化

  • 没有绝对的范式和反范式
  • 有时候适当冗余某个列(反范式)ÿ
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值