占用了自已需要的空间(也就是说较短的值占用的空间更小)。它使用额外的1-2个字节来存储值的长度。varchar能节约空间,所以对性能有帮助。然而,由于行的长度是可变的,它们在更新的时候可能会发生变化,这会引起额外的工作。当最大长度远大于平均长度,并且很少发生更新的时候,通常适合用varchar。这时候碎片就不会成为问题,还有你使用复杂的字符集,如utf-8时,它的每个字符都可能会占用不同的存储空间。varchar存取值时候,MySQL不会去掉字符串末尾的空格。
?
char:固定长度,char存取值时候,MySQL会去掉末尾的空格。Char在存储很短的字符串或长度近似相同的字符的时候很有用。例如,char适用于存储密码的MD5哈希值,它的长度总是一样的。对于经常改变的值,char也好于varchar,因为固定长度的行不容易产生碎片,对于很短的列,char的效率也高于varchar。Char(1)字符串对于单字节字符集只会占用1个字节,而varchar(1)则会占用2个字节,因为有一个字节用来存储其长度。
?
Char和varchar的兄弟类型为binary和varbinary,它们用于保存二进制的字符串,二进制字符串的传统的字符串很类似,但是它们保存的是字节而不是字符。填充也有所不同,MySQL使用\0(0字节)填充binary值,而不是空格,并且不会在获取数据的时候把填充的值截掉。
?
使用varchar(5)和varchar(200)保存“hello”占用的空间是一样的,但是使用较短的列有很大的优势,较大的列会使用更多的内存,因为MySQL通常会分配固定大小的内存块来保存值。这对排序或使用基于内存的临时表尤其不好。同样的事情也会发生在使用文件排序或基于磁盘的临时表的时候。
?
一般不要使用 TEXT 数据类型,其处理方式决定了他的性能要低于char或者是varchar类型的处理。定长字段,建议使用 CHAR 类型,不定长字段尽量使用 VARCHAR,且仅仅设定适当的最大长度,而不是非常随意的给一个很大的最大长度限定,因为不同的长度范围,MySQL也会有不一样的存储处理?
?
BLOB和TEXT
?
BLOB和TEXT分别用二进制和字符形式保存大量数据。
?
事实在,它们各有自的数据类型家族:
?
字符类型有TINYTEXT, SMALLTEXT, TEXT, MEDIUMTEXT和LONGTEXT,
?
二进制类型有TINYBLOB, SMALLBLOB, BLOB, MEDICMBLOB, LONGBLOB,BLOB 等同于SMALLBLOB, TEXT等同于SMALLTEXT
?
和其它类型不同,MYSQL把BLOB, TEXT当成有实体的对象来处理,存储引擎通常会特别地保存它们。INNODB在它们较大的时候会使用单独的“外部”存储来进行保存,每个值在行里面都需要1-4字节,并且还需要足够的外部存储空间来保存实际的值。
?
BLOB和TEXT唯一的区别就是BLOB保存的是二进制数据,没有字符集和排序规则,TEXT保存的是字符数据,有字符集和排序规则。
?
MYSQL对BLOB、TEXT列的排序方式和其它类型不同,它不会按照字符串的长度进行排序,而只是按照MAX_SORT_LENGTH规定的前若干个字节进行排序,如果只按照开始的几个字符排序,就可以减少MAX_SORT_LENGTH的值或使用ORDER BY SUBSTRING(COLUMN, LENGTH)。MYSQL不能索引这些数据类型的完整长度,也不能为排序而使用索引。
?
强烈反对在
数据库中存放 BLOB 类型数据,虽然
数据库提供了这样的功能,但这不是他所擅长的,我们更应该让合适的工具做他擅长的事情,才能将其发挥到极致
?
ENUM和SET
?
ENUM的内部存储机制是采用TINYINT或SMALLINT(并非CHAR/VARCHAR),而且即使需要增加新的类型,只要增加于末尾,修改结构也不需要重建表数据,ENUM列可以存储65535个不同的字符串,MYSQL以非常紧凑的方式保存了它们,根据列表中值的数量,MYSQL会把它们压缩到1-2个字节中,MYSQL在内部会把每个值都保存为整数,以表示值在列表中的位置,并且还保留了一份“查找表”来表示整数和字符串在表的.FRM文件中的映射关系。
?
ENUM最不好的一面是字符串是固定的,如果需要添加或者删除字符串必须使用ALTER TABLE,因此,对于一系列未知可能会改变的字符串,使用ENUM就不是一个好主意,MYSQL在内部的权限表中使用ENUM来保存Y值和N值。
?
由于MYSQL把每个值保存为整数,并且须进行查找才能把它转换成字符串形式,所以ENUM有一些开销。这通常可以由它们较小的大小进行弥补,但不总是这样,在特定情况下,把CHAR或VARCHAR列和ENUM列进行联接,可能会比联接另一个CHARA或VARCHAR列慢。
?
对于确定属性的字段,可以尝试使用SET类型,即使存在多种属性,同样可以游刃有余,可以结合FIND_IN_SET来使用,记住千万别用CHAR/VARCHAR来存储枚举数据
?
3、日期和时间类型
?
For example, TIME(0), TIME(2), TIME(4), and TIME(6) use 3, 4, 5, and 6 bytes, respectively. TIME andTIME(0) are equivalent and require the same storage
?
可以使用多种类型来保存各种日期和时间值,比中year和date,MySQL能存储的最细的时间粒度是秒,然而它可以用毫秒的粒度进行暂时的运算。
?
有几种相似的数据类型:DATETIME、TIMESTAMP和INT
?
DATETIME:范围是:1000-01-01 00:00:00 到 9999-12-31 23:59:59,与时区无关。使用了8个字节存储空间,可以使用NOW()变量来自动插入系统的当前时间
?
TIMESTAMP:保持了自1970年1月1日午夜(格林尼治标准时间)以来的秒数,和UNIX的时间戳相同。只使用了4个字节存储空间。可以用UNIX_TIMESTAMP()函数把日期转换为UNIX时间戳。显示的值依赖于时区,MYSQL服务器、操作系统及客户端连接都有时区设置。因此,保存0值的TIMESTAMP实际显示的时间是美国东部的时间1969-12-31 19:00:00,与格林尼治标准时间(GMT)相差5小时。最后,TIMESTAMP默认是NOT NULL,这也和其它的数据类型不一样
?
INT:占用4个字节;建立索引之后,查询速度快;条件范围搜索可以使用使用BETWEEN;可以使用FORM_UNIXTIME进行格式化
?
结论
?
INT适合需要进行大量时间范围查询的数据表
?
DATETIME类型适合用来记录数据的原始的创建时间,因为无论你怎么更改记录中其他字段的值,datetime字段的值都不会改变,除非你手动更