第四章
选择数据类型,几个简单的原则:
- 更小的通常更好
- 简单就好,比如使用MySQL内建datetime、timestamp,不使用字符串存储时间。使用整数存储IP地址
SELECT INET_ATON('192.168.1.212'), INET_NTOA(3232235988)
。 - 尽量避免NULL
摘要
- 当数据量比较大时候,可以考虑使用BIGINT代替DECIMAL,将存储的货币单位根据小数位数乘以相应倍数。
- varchar 需要1或者2个额外字节存储字符串的长度,如果列的最大长度<=255字节,需要1个字节,否则2个字节。另外,varchar变长当更新时候,有可能会导致分裂页进行存储。Innodb会把过长的varchar存储为BLOB。
- 下面情况适用varchar合适的: 字符串最大长度比平均长度大很多;列更新很少,所以碎片不是问题;使用了UTF-8复杂字符集,每个字符串使用不同的字符数存储。
- varchar(255),定义的不是字节数,是字符数。
- char(3)如果采用单字节字符集,存储需要3个字节。而varchar(3),需要4个字节
- varchar(5)和varchar(200)存储 'hello'的空间开销是一样的,那么使用更短列有什么优势呢?事实证明有很大优势。更大的列会消耗更多的存储。因为MySQL通用会分配固定大小的内存块来保存内部值。尤其是使用内存临时表进行排序或操作时特别糟糕,在利用磁盘临时表也同样糟糕。
- 不使用ENUM类型,如COLOR,现在要加一个YELLOW枚举,需要Alter table。如果改变原始枚举值,比如把WHITE变为RED,存储变为''空字符串。
选择标示列类型
标示列,一般是主键或者关联列。
- 整数是标识列列的最后选择,很快并且可以Auto_increment
- 如果可以避免使用字符串作为标示列,很消耗空间并且比数字慢。最多有6倍的性能下降。insert语句使用字符串做主键可能会导致页分裂、磁盘随机访问,innodb还会导致聚簇索引碎片。如果一定要使用UUID,应该移除-,使用UNHex函数转换为16字节数字,并存储在BINARY(16)[blob]列,检索是通过HEX函数来格式为十六进制。所以还是推荐使用整数。
范式和反范式
反范式是值schema把数据都放一张表里,可以很好避免关联
计数器表的优化
如果有一张表CREATE TABLE hit_counter(cnt int unsigned not null)
记录点击次数,每次更新这行数据事务来说,都有一个全局的互斥锁mutex。要获得更高性能可以采用分治思想,把热点行数据分拆。
CREATE TABLE hit_counter( slot tinyint unsigned not null primary key,
cnt int unsigned not null);
insert INTO hit_counter(slot, cnt) VALUE (RAND() * 100, 1)
ON DUPLICATE KEY UPDATE cnt = cnt + 1;
网友评论