【笔记】高性能MySQL(第三版)——第4章:MySQL基准测试

4.1选择优化的数据类型

  • 更小的通常更好。一般应该尽可能使用能正确存储数据的最小数据类型,更小的数据类型通常更快,因为他们占用更少的磁盘、内存和CPU缓存,并且处理需要的CPU周期更少。
  • 简单就好。整型比字符串操作代价更低。 两个例子:1、应该用MySQL内建的类型来记录日期和时间 2、应该用整型来存储IP地址(IP地址正好是32位,而且都是01值,可以转换成整形数值)
  • 尽量避免null。可为NULL的列使得索引、索引统计和值比较都更复杂。NULL列被索引的时候,每个索引记录都需要一个额外的字节。NULL列会使用更多的存储空间,在MySQL也需要特殊处理。(通常把可为NULL的列改为NOT NULL带来的性能提升比较小,但是如果打算在这个列上建索引,那就应该避免设计为可为NULL。
  • 例外:InnoDB使用单独的位(bit)存储NULL,所以对于稀疏数据(很多值为NULL)有很好的空间效率。
  • 为数据列选择数据类型时,先确定合适的大类型:数字,字符串,时间等。datetime和timestamp可以存储相同类型的数据:日期和时间、精确到秒。然而timestamp只使用datetime一半的存储空间,并且会根据时区进行变化,具有特殊的自动更新能力。但是timestamp允许的时间范围要小的多,有时候它的特殊能力会成为障碍。

4.1.1 整数类型

  1. 存储整数的类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。分别使用的存储空间为8,16,24,32,64位存储空间。它们而已存储的范围为: (2)N1 2N1 ,N是存储空间的位数。
  2. 整数类型有可选的UNSIGNED属性,表示不允许负值,这大致可以使整数的上限提升一倍。
  3. MySQL可以为整数类型指定宽度,例如INT(11),对于大多数应用这是没有意义的。它不会限制值的合法范围。只是规定了MySQL的交互工具(客户端)用来显示字符的个数。对于存储和计算来讲INT(1)和INT(20)是一样的。

4.1.2 实数类型

  1. float和double类型支持使用标准的浮点运算进行近似计算。(float4字节,double8字节)
  2. DECIMAL类型用于存储精确的小数。在MySQL5.0+版本中DECIMAL类型支持精确计算。(每4个字节存储9位数字,因为还是转化为2进制来存储,4字节也就是32位,最大的位数是10位)
  3. 浮点和DECIMAL类型都可以指定精确度。对于DECIMAL列,可以指定小数点前后所允许的最大位数。这会影响列的空间消耗。

4.1.3 字符串类型(感觉比较常问到)


VARCHAR
  • VARCHAR: 用于存储变长字符串,使用额外的存储空间来存储字符串长度。如果UPDATE时使得行比原来更长,这时需要额外的工作,MyISAM会将行拆分成不同的片段存储,InnoDB则需要分裂也来使行可以放进页内。会保留存储字符串的末尾空格。
  • 需要1或者2个额外字节记录字符串长度。如果列的最大长度小于或者等于255,则值需要1个字节表示,否则使用2个字节。
  • VARCHAR适用于字符串列的最大长度比平均长度大很多;列更新很少,所以碎片不是问题;使用了像UTF8这样负责的字符集,每个字符使用不同的字节数进行存储。
CHAR
  • CHAR:定长(也就是分配固定的空间),会删除字符串末尾空格
  • CHAR适合存储定长或长度接近的数据;对于经常变更的数据CHAR不容易产生碎片;对于非常短的列CHAR在存储空间上更有效率
VARCHAR(1)比CHAR(1)需要更多空间,因为VARCHAR还需要一个字节来记录长度的额外字节

BLOB和TEXT类型

  1. 都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。
  2. 字符类型:TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT。
  3. 二进制类型:TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB。
  4. 与其他的类型不同,MySQL把每个BLOB和TEXT值当作一个独立的对象处理。存储引擎在存储时,通常会做特殊处理。当BLOB和TEXT值太大时,InnoDB会使用专门的“外部”存储区域进行存储,此时每个值在行内需要1~4个字节存储一个指针,然后在外部存储区域存储实际的值。
  5. BLOB和TEXT之间的不同是BLOB类型存储的是二进制数据,没有排序规则或字符集,而TEXT类型有字符集和排序规则。
  6. MySQL对BLOB和TEXT进行排序与其他类型时不同的:它只对每个列的最前max_sort_length字节而不是整个字符串做排序。

ENUM
  • 使用枚举(ENUM)代替字符串。对于枚举类型在表.frm文件中会保存“数字-字符串”的映射关系,行内存储的是值在列表中的位置(从1开始),排序的时候是按照列表中声明的顺序,使用枚举类型可以减少表的大小。

  • 枚举类型最大的缺点在于增加或删除字符串的时候必须使用ALTER TABLE, 除非只是在末尾添加字符串,不然需要重建整个表。枚举列在进行关联查询的时候,如果和CHAR OR VARCHAR关联,性能会比较差甚至不如直接用字符串,但是枚举和枚举关联,性能不错。在某些情况下,即使可能出现ENUM和VARCHAR关联的情况这也是值得的,因为可以减少I/O。



4.1.4 时间类型

  1. DATETIME 
    这个类型能保存的值:从1001年到9999年,精度为妙。它把时间和日期封装到格式YYYYMMDDHHMMSS的整数中,与时区无关,保存在8字节中。
  2. TIMESTAMP
  • 它保存了从1970年1月1日午夜一来的秒数,它与unix时间戳是相同的。
  • 但它只用4个字节,所以表示的范围小一点。只能表示1970到2038年。
  • MySQL中FROM_UNIXTIME()函数把unix时间戳转换为日期。
  • UNIX_TIMESTAMP()函数将日期转换为Unix的时间戳。
  • 依赖于时区。

位数据类型

  • BIT: BIT列最长64位。BIT(64)需要8个字节来存储。MySQL把BIT当作字符串类型而非数字类型,所以查询BIT列的时候得到的是所存储的二进制值作为ASCII码对应的字符串,如果用BIT列和其他数字比较或计算,那么查询到的是数字。这个相当费解,建议谨慎使用。
  • SET: 在MySQL内部以一系列打包的位的集合来表示,可以有效的利用存储空间,并且有FIND_IN_FIELD(), FIELD()这样的函数可以在查询时使用。主要缺点是改变列的定义代价比较大。
  • 一种替代SET的方案就是用一个整数包装一系列的位。类似于Linux文件系统的权限管理那样。

特殊类型

IP地址: 通过INET_ATON()和INET_NTOA()函数在IP地址和无符号整数之间做转换。


范式和反范式

  • 范式优点:
    • 范式化的更新操作比反范式化要快
    • 当数据较好地范式化的时候,就只有很少或者没有重复数据,所以只需要修改更少的数据
    • 范式化的表通常更小,可以更好的放在内存里,所以执行操作会更快
    • 很少有多余的数据意味着检索列表数据时更少需要DISTINCT和GROUP BY这样的语句。
  • 范式缺点:
    • 通常需要关联
    • 代价昂贵,也可能是一些索引策略无效
  • 反范式优点:
    • 不需要关联查询
  • 反范式缺点:
    • 数据冗余
    • 更新和插入操作需要做更多

缓存表和汇总表

这个感觉就看具体需求了,对于缓存或者汇总的数据实时性要求有多高,然后采取不同的策略。

影子表:是指在一张真是表“背后”创建同样的表,然后建好之后通过原子的重命名操作切换。

mysql> DROP TABLE IF EXISTS my_summary_new, my_summary_old;
mysql> CREATE TABLE my_summary_new LIKE my_summary;
mysql> RENAME TABLE my_summary TO my_summary_old, my_summary_new TO my_summary;

物化视图

MySQL并不支持物化视图,可是使用开源工具Flexviews来实现。

加快ALTER TABLE的速度

ALTER TABLE一般都很慢,操作将导致MySQL服务中断。一般来说是会新建个表,然后从旧表读取数据插入到新表中,这样效率很慢。

但并不是所有的都这么慢,比如修改一个列的默认值有两种办法:

mysql> ALTER TABLE film MODIFY COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;

mysql> ALTER TABLE file ALTER COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5

第一种方法是通过上面所说的读取插入的方式。 第二种方法会直接修改.frm文件不涉及数据,所以很快。

下面有一些修改表的操作是不需要重建表的:

  • 移除一个列的AUTO_INCREMENT属性
  • 增加、移除或更改ENUM和SET常量。如果移除的是已经有行用到的,查询将返回一个空字符串。

基本思路是为想要的表结构创建一个新的.frm文件,然后替代已有的那个:

  • 创建相同结构的表,并进行修改
  • 执行FLUSH TABLES WITH READ LOCK。这将关闭所有正在表,并且禁止任何表被打开。
  • 交换.frm文件
  • 执行UNLOCK TABLES释放锁。

为InnoDB表增加索引的时候也可以尝试一种比较骇客的方法(官方并不支持,注意备份数据):

  • 用需要的表结构创建一张表,但是不包括索引。
  • 载入数据到表中以构建.MYD文件
  • 按照需要的接口创建另外一张空表,这次包含索引。这会创建需要的.frm和.MYI文件。
  • 获取读锁并刷新表。
  • 重命名第二张表的.frm和.MYI文件,让MySQL以为是第一张表的文件。
  • 释放读锁。
  • 使用REPAIR TABLE来重建表的索引。














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值