高性能mysql 第4章 Schema与数据类型优化
基本原则:
- 更小的通常更好:占用更少的磁盘 内存和cpu缓存。如varchar(2)和varchar(100)。
- 简单就好:比如整形比字符型代价更低。使用日期型来存储日期而不是字符串。使用整形存储ip地址。
- 尽量避免null:如果可以 加上not null约束。因为可以null的列使索引,索引统计,值比较都变得复杂。通常把可为null的列改为not null带来的性能提升比较小,调优时没有必要首先修正这种情况来排查问题。但是如果计划在列上建立索引,如果可以保证是not null,那么尽量加上。
整数类型:
tinyint,smallint.,mediumint,int,bigint.分别是1,2,3,4,8个字节。也就是8,16,24,32,64位,存储的数据范围为-2(n-1)到2(n-1)-1。
如果使用unsigned属性,那么表示不允许负数。那么存储的范围就变成了0到2n-1。
mysql可以为整数类型制定宽度,如int(1)和int(20),只是多了一个宽度约束,在内部,他们都是int。
实数类型:
实数是带小数点的数字。然而他们的作用并不局限与这个。如可以使用decimal存储比bigint还要大的整数。
不精确数字类型(浮点类型):float double,他们分别为4个字节,8个字节。
关于指定精度,书上一掠而过了,以下内容来自网络:
float数值类型用于表示单精度浮点数值,而double数值类型用于表示双精度浮点数值,float和double都是浮点型,而decimal是定点型;MySQL 浮点型和定点型可以用类型名称后加(M,D)来表示,M表示该值的总共长度,D表示小数点后面的长度,M和D又称为精度和标度,如float(7,4)的 可显示为-999.9999,MySQL保存值时进行四舍五入,如果插入999.00009,则结果为999.0001。
decimal最多只能65个数字,也就是是那面总的M最大只能是65。
同样大小的decimal要比float和double占据更大的空间,耗费更多的cpu,所以如果不是要求精确的计算(如财务计算),最好不要使用decimal。
书上提到一种委婉的办法,将有小数的decimal数字成与一定的倍数,如1万倍,然后存储为bigint。可以提升性能。我在想这种委婉的办法带来的性能提升划算吗。可能会在极端的环境下使用吧。
字符串类型:
char和varchar
char在存储上是定长的。在定义的时候需要指定长度。数据库会分配这么大长度的空间。
varchar是变长的,一旦对一个varchar进行update,新的数据变得更长,那么可能数据库需要做存储空间的移动才能容下,或者新的数据变得更小,那么就可能产生碎片。
char和varchar在逻辑上基本是一样的,差别是在存储。
char和varchar在逻辑上的差别是:char在插入的时候会将字符串末尾的空格删除。
blog:存储二进制。text:存储大文本字符串。他们两个都有tiny,small,medium,long的类型。
mysql对于blog和text的排序跟其他的是不一样的,它只对每个列的前max_sort_length(可以配置)字节而不是整个字符串进行排序。
日期型:
datetime和timestamp
datetime可以保存1001-9999年的日期,精度为妙,与时区无关。
timestamp可以保存1970—2038年的日期,精度也为秒,依赖于时区。
mysql没有定义精度小于秒的日期类型,如果需要只能自己用其他数据类型实现。
其他:
疑惑:作者在书上说,建议对id列使用数字,最好使用递增的数字来记录id,如果要使用uuid,一定要-去掉,作为数字存储。如果这样的话,mysql的本身的性能太依赖于使用者的数据类型选择了。如果说用uuid做主键都成了一种负担。
mysql限制一个查询中join的数量控制在61张表,作者建议控制在12个表以内。
mysql不支持物化视图。
避免使用mysql已经遗弃的特性,如指定浮点数的精度(为什么?),或者整数的显示宽度。
小心使用enum和set。尽量不要使用bit。
enum是枚举类型。bit是位,set是位的集合。