选择优化的数据类型
更小的通常更好:占内存、磁盘、cpu缓存更少,但是要够用。
简单的更好
避免使用null:设计索引的时候避免使用可以为null的列
timestamp需要datetime一半的空间,但是时间范围会小
1 整数类型
tinyint8、smallint16、mediumint24、int36、bigint64
unsigned不允许负值
整数类型计算用bigint
2 实数类型
带有小数部分的数字
decimal是存储类型,不支持直接计算,计算的时候会转换为double,可以指定小数点前后允许的最大位数。
float占4字节,double占8字节
上面讨论的都是存储类型,mysql用double类型进行计算
可以用bigint代替decimal,只需要乘相应的倍数。
3 字符串类型
varchar:可变字符,额外1-2字节记录长度,更新的时候会有碎片化的问题,如果页内空间不够myisam会把行拆成不同的片段存储,innodb会分裂页。
char:定长,会删除末尾的空格,用空格填充
Binary:存储二进制字节码,用\0字节填充
varbinary:存储二进制字节码
字节比较比字符比较简单,速度更快
给varchar分配更长的列不好,是因为mysql会分配固定的内存空间给要存储的值,所以这种情况下使用内存临时表进行排序或操作的时候会很不好,用磁盘临时表排序的时候也很糟糕。
Bolb:存储的是字节码
Text:存储的是字符,有字符集和排序规则
这俩类型视为一个对象,存储的时候如果值太大会用外部存储区域来存储,此时每个行内用1-4个字节存储一个指针来指向外部存储的区域,外部存储区域存储真实的值。
这俩排序不是对整个数据进行排序,而是对前面的max_sort_length字节进行排序
用到这俩类型的地方用substring(column,length)来转换成字符串类型,这样就可以使用临时内存表,要不然会使用隐式临时表,即磁盘临时表
extra为using temporary就是用了隐式临时表
ENUM枚举类型:会把每个值在列里映射为整数类型,把整数和数据对应表存在.frm文件里,按内部定义的整数进行排序,字符串列表是固定的。
在查找表的时候用整数主键避免采用基于字符串的值进行关联。
4 日期和时间类型
mysql储存的时间粒度最小为秒。
datetime从1001年到9999年,8个字节的存储空间
timestamp:1980.1.1-2038,4字节的存储空间
5 位数据类型
BIT,最大的长度是64位
6 选择标识符
整形很好,尽量少选emum和set
避免使用字符串,myisam对字符串类型通常压缩
避免随机函数生成的值,可能会在很大的空间里,使得insert语句变满:1、增加随机IO,可能会导致页分裂,产生聚簇索引碎片,导致缓存效果很差。
mysql scheme设计中的陷阱
列数不能太多
关联不能太多,单个查询最好在11个表内做关联
不能过度使用枚举
不一定使用null就是不好
范式与反范式
1 范式的优点和缺点
更新操作更快,重复数据更少,范式后的表更小,更容易放在内存中处理,可能更少的使用distinct和group by。
缺点是通常需要关联,可能使一些索引策略无效
2 反范式的优点和缺点
避免了关联,最坏的情况是全表扫描,这样也避免了随机IO
3 混用范式和反范式
缓存表和汇总表
1 物化视图
预先计算并存储在磁盘上的表
2 计数器表
加快alter table操作的速度
有两种技巧:1、是在一个不提供服务的机器上执行alter table操作,然后和提供服务的主库切换2、是根据要求创建一个跟原表无关系的新表,然后重命名和删表来交换这两个表。
1 只修改.frm文件
下面操作可以不用建新表:
1、移除一个列的AUTO_INCREMENT
2、增加、移除或更改ENUM和set常量。
过程如下:
1、创建一个有相同结构的空表,并修改
2、执行FLUSH TABLES WITH READ LOCK锁住
3、交换.frm文件
4、UNLOCK TABLES打开锁
2 快速创建MYISAM索引
对于非唯一索引,可以先删掉,然后增加新的列,然后再加上索引
可以用骇客的方法。