一、背景
根据业务需求,发现以前的同事在设计表的时候,很多字段都没有设置默认值。在mysql5.7版本之后,没有设定默认值的字段,在严格模式下是很容易报错的,所以我这边需要先给每个字段加上一个默认值。
对于常见的int类型,默认值为0就好,但是对于varchar类型呢,默认值是设置为”还是Null呢?
二、‘’和null的区别
1、占用空间问题
(1)、c语言:
‘\0’,这个表示空,需要消耗存储空间的。
NULL,则表示连这个\0都没有。
(2)、mysql:
空值(’’)是不占用空间的
MySQL中的NULL其实是占用空间的。官方文档说明:
“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.” 1
可见为了表示某个字段是否为空是需要额外开辟空间存储Null值,而在C语言中空值’不占用存储空间。
不仅如此,不使用NULL可以提高索引效率,因为树形索引结构中将NULL也视作一般数据节点。
2、上面说到了null会影响索引效率
其实我们在初学mysql的时候,都会看到一段话,那就是mysql建议字段最好为不要为null,尽量为not null。
原话:
尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化。因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
null会影响索引的统计,一般会默认null为同一个值,这样这个索引的筛选价值就降低了,影响优化器的判断。当然也可以调整参数,使得null被认为是不同的值。
3、结论
在设置默认值的时候,尽量不要用Null来当默认值,如果字段是int类型,默认为0,如果是varchar类型,默认值用空字符串(’’)会更好一些。带有null的默认值还是可以走索引的,只是会影响效率。当然,如果确认该字段不会用到索引的话,也是可以设置为null的
在设置字段的时候,可以给字段设置为 not null ,因为 not null 这个概念和默认值是不冲突的。我们在设置默认值为”的时候,虽然避免了null的情况,但是可能存在直接给字段赋值为null,这样数据库中还是会出现null的情况,所以强烈建议都给字段加上 not null。
就这样的:
alter table 数据表 modify 字段名
VARCHAR (255) NOT NULL DEFAULT '';
1
三、在统计时,”和null的区别
这部分建议参考博客:
MySQL 中NULL和空值的区别
结论:
在进行count()统计某列的记录数的时候,如果采用的NULL值,会别系统自动忽略掉,但是空值是会进行统计到其中的。
判断NULL 用IS NULL 或者 is not null,SQL 语句函数中可以使用ifnull()函数来进行处理,判断空字符用 =’‘或者 <>’'来进行处理
对于MySQL特殊的注意事项,对于timestamp数据类型,如果往这个数据类型插入的列插入NULL值,则出现的值是当前系统时间。插入空值,则会出现 ‘0000-00-00 00:00:00’
对于空值的判断到底是使用is null 还是 =’'要根据实际业务来进行区分。
四、关于char和varchar的选用
1、定义
众所周知的,char是定长,而varchar是变长。
char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足.(在检索操作中那些填补出来的空 格字符将被去掉)在varchar(M)类型的数据列里,每个值只占用刚好够用的字节再加上一个用来记录其长度的字节(即总长度为L+1字节)。
2、哪个更合适
对于MyISAM表,尽量使用Char,对于那些经常需要修改而容易形成碎片的myisam和isam数据表就更是如此,它的缺点就是占用磁盘空间;
对于InnoDB表,因为它的数据行内部存储格式对固定长度的数据行和可变长度的数据行不加区分(所有数据行共用一个表头部分,这个标头部分存放着指向 各有关数据列的指针),所以使用char类型不见得会比使用varchar类型好。事实上,因为char类型通常要比varchar类型占用更多的空间, 所以从减少空间占用量和减少磁盘i/o的角度,使用varchar类型反而更有利。
3、结论
在确定字段为短小且定长的时候,用char会好一些
在某字段需要频繁改写的时候,用char会好一些(因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。
设计varchar()值的时候,不要一股脑的都用varchar(255):mysql会把表信息放到内存中(查询第一次后,就缓存住 了,linux下很明显,但windows下似乎没有,不知道为啥),这时内存的申请是按照固定长度来的,如果varchar很大就会有问题。
关于varchar(255)和varchar(256) :根据mysql官方文档,varchar(255)需要一个字节记录字段的长度 256以上需要两个字节记录长度。设置长度超过256会有点浪费。
因为在业务中使用innoDB多一些,所以尽量还是用varchar好一些