选择优化的数据类型
字符串类型
VARCHAR
VARCHAR
类型用于存储可变长字符串。它比定长类型更节省空间,因为它仅使用必要的空间。
VARCHAR
需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示;否则使用2个字节。
CHAR
CHAR
类型是定长的:MySQL
总是根据定义的字符串长度分配足够的空间。当存储CHAR
值时,MySQL
会删除所有的末尾空格。
CHAR
适合存储很短的字符串,或者所有值都接近同一个长度。;对于经常变更的数据,CHAR
也比VARCHAR
更好,因为定长的CHAR
类型不容易产生碎片。对于非常短的列,CHAR
比VARCHAR
在存储空间上也更有效率。
日期和时间类型
除了特殊情况,通常应该尽量使用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
属性 - 增加、移除,或更改
ENUM
和SET
常量。如果移除的是已经有行数据用到其值的常量,查询将会返回一个空字符串值
基本的技术是为想要的表结构创建一个新的.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;
这个技巧能够发挥作用,是因为构建索引的工作被延迟到数据完全载入以后,这个时候已经可以通过排序来构建索引了。这样做会快很多,并且使得索引树的碎片更少、更紧凑。