高性能MySQL - Schema与数据类型优化

2016/3/21 posted in  数据库

选择优化的数据类型

字符串类型

VARCHAR

VARCHAR类型用于存储可变长字符串。它比定长类型更节省空间,因为它仅使用必要的空间。

VARCHAR需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示;否则使用2个字节。

CHAR

CHAR类型是定长的:MySQL总是根据定义的字符串长度分配足够的空间。当存储CHAR值时,MySQL会删除所有的末尾空格。

CHAR适合存储很短的字符串,或者所有值都接近同一个长度。;对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。对于非常短的列,CHARVARCHAR在存储空间上也更有效率。

日期和时间类型

除了特殊情况,通常应该尽量使用TIMESTAMP,因为它比DATETIME空间效率更高。

特殊类型数据

人们经常使用VARCHAR(15)列来存储IP地址。然而,它们实际上是32位无符号整数,不是字符串。用小数点将地址分成四段的表示方法只是为了让人们阅读容易。所以应该用无符号整数存储IP地址。

范式和反范式

范式的优点和缺点

范式化通常能够带来的好处

  • 范式化的更新操作通常比反范式化要快
  • 当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据
  • 范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快
  • 很少有多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句。

范式化设计的schema的缺点是通常需要关联。稍微复杂一些的查询语句在符合范式的schema上都可能需要至少一次关联,也许更多。

反范式的优点和缺点

反范式化的schema因为所有数据都在一张表中,可以很好地避免关联。

如果不需要关联表,则对大部分查询最差的情况——即使表没有使用索引——是全表扫描。当数据比内存大时,这可能比关联要快得多,因为这样避免了随机I/O。

混用范式化和反范式化

加快ALTER TABLE操作的速度

不是所有的ALTER TABLE操作都会引起表重建。例如,有两种方法可以改变或者删除一个列的默认值(一种方法很快,另一种则很慢)。

假如要修改电影的默认租赁期限,从三天改到五天。下面是很慢的方式:

ALTER TABLE sakila.film
MODIFY COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;

SHOW STATUS显示这个语句做了1000次读和1000次插入操作。换句话说,它拷贝了整张表到一张新表,甚至列的类型、大小和可否为NULL属性都没改变。

另外一种方法是通过ALTER COLUMN操作来改变列的默认值:

ALTER TABLE sakila.film
ALTER COLUMN rental_duration SET DEFAULT 5;

这个语句会直接修改.frm文件而不涉及表数据。所以,这个操作是非常快的。

只修改.frm文件

下面这些操作是有可能不需要重建表的:

  • 移除(不是增加)一个列的AUTO_INCREMENT属性
  • 增加、移除,或更改ENUMSET常量。如果移除的是已经有行数据用到其值的常量,查询将会返回一个空字符串值

基本的技术是为想要的表结构创建一个新的.frm文件,然后用它替换掉已经存在的那张表的.frm文件,像下面这样:

  • 创建一张有相同结构的空表,并进行所需要的修改
  • 执行FLUSH TABLES WITH READ LOCK。这将会关闭所有正在使用的表,并且禁止任何表被打开。
  • 交换.frm文件
  • 执行UNLOCK TABLES来释放第二步的读锁

快速创建MyISAM索引

为了高效地载入数据到MyISAM表中,有一个常用的技巧是先禁用、载入数据,然后重新启用索引:

ALTER TABLE test.load_data DISABLE KEYS;
-- load the data
ALTER TABLE test.load_data ENABLE KEYS;

这个技巧能够发挥作用,是因为构建索引的工作被延迟到数据完全载入以后,这个时候已经可以通过排序来构建索引了。这样做会快很多,并且使得索引树的碎片更少、更紧凑。