更小通常更好
一般来说,要试着使用能正确地存储和表示数据的最小类型。更小的数据类型通常更快,占用磁盘空间、内存、CPU缓存,需要的CPU周期更少。
但是要确保不会低估需要保存的值,在架构中的多个地方增加数据类型的范围是一件极其费时费立的工作,如果不能去顶需要的类型,就选择你认为不会超出范围的最小类型。
(如果系统不是非常繁忙或不会保存太多的数据,在或者还处于设计的早期,就可以在以后轻易地更改它)
简单就好
越简单的数据类型,需要的CPU周期就越少。例如,比较整数的代缴小于比较字符,因为字符集和排序规则字符集比较更复杂。
尽量避免null
要尽可能地把字典filed定义为not null。即使应用程序无须保存NULL(没有值)。
mysql难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂,可空列需要更多的存储空间,还需要mysql内部进行特殊处理。当可空列被索引的时候,每条记录都需要一个额外的字节,还能导致MyISAM中固定大小的索引变成可变大小的索引。
把null列改为NOT NULL带来的性能提升很小,所以除非确定它引入了问题,否则就不要把它当成优先的优化措施。如果计划时队列进行索引,就要尽量避免把它设置为空。
决定特定列的数据类型的第一步就是大致决定数据类型:数字、字符串、时间等
第二部:确定特定类型。许多mysql数据类型能够保存同类的数据,但是存储范围、精度、或物理空间却不同。
整数:
数字有两种类型:整数(Whole Number)和实数(Real Number).如果存储整数,就可以使用这几种整数类型
TINYINT、SMALLINT、MEDIUMINT、INT或BIGINT,他们需要8、16、24、32、64为存储空间。他们的范围为-2(n-)到2(n-1)-1,这里的N是所需要的存储空间的位数。
整数类型有可选的UNSIGNED属性,表示不允许为负数,并大致把正上限提高了一倍。例如:TINYINT UNSIGNED 保存的范围为0到255,而不是-127到128
SIGNED和UNSIGNED类型占用的存储空间是一样的,性能也一样。
你的选择将会决定mysql把数据保存在内存中还是磁盘上。然而,整数运算通常使用64位BIGINT整数,即使是32位架构也是如此。
mysql还可以对整数类型定义宽度,比如int(11)这对于大多数应用程序是没有意义的:它不会限制值的范围,只是规定了mysql的客户端用来显示字符的个数。对于存储和计算int(1)与Int(11)是一样的。
实数:
实数是有分数的部分。然而,他们并不仅仅是分数。可以使用DECIMAL保存比BIGINT还大的整数。
FLOAT和DOUBLE类型支持使用标准的浮点运算进行近似计算。如果想知道浮点运算到底如何进行,则需要研究平台浮点数的具体实现。
DECIMAL类型用于保存精确的小数。
比起DECIMAL类型,浮点类型保存同样大小的值使用的空间通常更少。FLOAT占用4个字节。DOUBLE占用8个字节,而且精度更高、范围更大。和整数一样,你选择的仅仅是存储类型。MYSQL在内部对浮点类型使用double进行计算。
字符串类型
varchar和char类型
字符串存储更存储引擎有关
varchar保存了可变长度的字符串。他能不固定长度类型占用更少的存储空间,因为它只占用自己需要的空间。例外情况是使用ROW_FORMAT=FIXED创建的MYISAM表,它为每行使用固定的长度空间,肯能会造成浪费。
varchar使用额外的1到2个字节来存储值的长度。varchar(255)则使用1个字节,否则使用2个字节。varchar(11)将会占用12个字节的存储空间,varchar(1000)占用1002个字节存储空间。
varchar能节约空间,所以对性能有帮助。但是,由于行的长度是可改变的,在更新的时候可能会发生变化,引起额外的工作。如果行的长度增加并不在适合原始的位置时,具体的行行为则会和存储引擎相关。例如:MYISAM会把行拆开,InnoDB则可能进行分页。另外的存储引擎还可能不会在合适的位置更新数据。
当最大长度远大于平均长度,并且很少发生更新的时候,通常使用varchar。这时候碎片就不会成为问题。当你使用复杂字符集,比如使用UTF-8时,它的每个字符都可能会暂用不同的存储空间。
char是固定长度的。当保存此类型的值时候,mysql会去掉任何末尾的空格。进行比较的时候,空格会被填充到字符串末尾。
char在存储很短的字符串或长度相近似相同的字符串的时候很有用。例如char适合用存储用户密码的MD5哈希值,它的长度总是一样的。char类型因为固定长度的行不容易产生碎片。对于很短的列,char的效率也高于varchar。char(1)字符串对于单字节字符集只会占用1个字节,但是varchar(1)则会占用2个字节。
char类型mysql是采用空格补齐的,如果存储的值确实需要空格那么,不可以使用char类型,因为 mysql 会将空格全部去掉。
char与varchar的兄弟类型为binary和varbinary,它们用于保存二进制字符串。二进制字符串和传统字符串很类似,但是保存的是字节,而不是字符。
它们在需要存储二进制数据并且想让mysql按照字节进行比较的时候是有用的。字节比字符的优势并不仅仅体现在大小写敏感上。mysql按照字节的数值进行比较,比按字符比较简单得多,效率也更高。
注意:如果不想在取值的时候,值发生改变,就不要使用BINARY类型,因为mysql会用\0把它填充到需要的长度。
BLOB和TEXT
BLOB和TEXT分别以二进制和字符形式保存大量数据
和其他类型不同,mysqlblob和text当成有实体的对象来处理,存储引擎通常会特别地保存它们。InnoDB在它们较大的时候会使用单独的“外部”存储区域来进行保存。每个值在行里都需要1到4个字节,并且还需要足够的外部存储空间来保存实际的值。
BLOB与TEXT的唯一区别就是BLOB保存的是二进制数据,没有字符集和排序规则,但是text有字符集和排序规则。
mysql对blob与text列的排序方式和其他类型不同:它不会按照字符串的完整长度进行排序,而只是按照max_sort_length规定的前若干个字节进行排序。如果只按照开始的几个字符排序,就可以减少max_sort_length的值或使用order by substring(column,length)
最好尽可能的避免使用BLOB和test类型。如果不能避免,就可以使用order by substring(column,length).把这些值转换为字符串,让它们使用内存中的临时表。要保证使用的字符串足够短,不要让临时表变得过大,以至于超过max_heap_size或tmp_table_size的大小,否则mysql会把表转换为磁盘上的myisam表。
日期和时间类型
mysql可以使用date和year等各种类型。mysql能存储的最细的时间粒度是秒。然而,它可以用毫秒的粒度进行暂时的计算。
DATETIME
这个类型能保存发范围的值,把时间转换为秒。把日期和时间封装到一个格式为YYYYMMDDHHMMSS的整数中,与时区无关。它使用了8个字节存储空间。在默认情况下,mysql以一种可排序、清楚的格式显示DATETIME值
TIMESTAMP和unix时间戳相同。timestamp只使用了4个字节的存储空间,因此它的范围比datetime小的多,他只能表示1970到2038年。mysql提供了FROM_UNIXTIME()函数把UNIN时间戳转换为日期,并提供了UNIX_TIMESTAMP()函数,把日期转换为unix时间戳。
TIMESTAMP显示的值依赖于时区。Mysql服务器、操作系统及客户端连接都有时区设置。
位集数据类型
BIT
可以使用bit列,并且在一列中保存一个或多个true/false值。BIT(1)定义了一个只含有一个二进制的字段,BIT(2)能保存2位,bit列的最大长度是64位。
BIT的行为在不同个存储引擎之间是不同的。(未完待续)(不推荐使用)。
set(待续)
enum(待续)