Mysql字段类型
整型
整型类型:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT分别使用8、16、24、32、64位空间存储
MYSQL可以为整数类型指定宽度,例如:INT(11),对大多数应用这是没有意义的,它并不会限制值的合法范围,只是规定了MYSQL的一些交互工具(例如Mysql客户端)用来显示字符的个数。(补充位数)。对于存储和计算来说,INT(1)和INT(11)是相同的
MYSQL有符号和无符号使用相同的存储空间,具有相同的性能
浮点和DECIMAL类型都可以指定精度。对于DECIMAL列,可以指定小数点前后允许的最大位数。这会影响列的空间消耗。MYSQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。例如,DECIMAL(18,9)小数点两边将存储9个数字,一共使用9个字节:小数点前的数字9位用4个字节,小数点后的数字9位用4个字节,小数点本身占用1个字节
金钱选择,INT、BIGINT、FLOAT、DOUBLE、DECIMAL
- DECIMAL存储比BIGINT还大的整数
- DECIMAL存储的小数比FLOAT、DOUBLE精准。DECIMAL还支持精准计算
- 浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的空间。FLOAT使用4个字节存储,DOUBLE占用8个字节,相比FLOAT有更高的精度和更大的范围。MYSQL使用DOUBLE作为内部浮点计算的类型
- 因为需要额外的空间和计算开销(小数点占用空间),所以尽量只在对小数进行精确计算时才使用DECIMAL-例如存储财务数据。数据量比较大的时候,可以考虑使用BIGINT代替DECIMAL
字符串
VARCHAR
- mysql4.x,表示字节数
- mysql5.x及以上,表示字符数
VARCHAR类型用于存储可变字符串,它比定长类型更节省空间,因为它仅使用必要的空间(例如,越短的字符串使用越少的空间)。有一种情况列外,如果MYSQL表使用ROW_FORMAT=FIXED创建的话,每一行都会使用定长存储,这会很浪费空间
VARCHAR需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节。例如:VARCHAR(10)的列需要11个字节空间存储,VARCHAR(1000)的列需要1002个字节,因为需要二个字节存储长度信息
VARCHAR节省了存储空间,但由于行是变长的,在UPDATE时可能使行变得比原来更长,这会导致额外的工作。如果一个行占用的空间增长,并且在页内没有更多的空间可以存储。不同的存储引擎做法不一样。MyISAM会将行拆成不同的片段存储,Innodb则需要分裂页使行可以放进页内。
- 其中一个汉字或是一个字母表示一个字符
- 一个汉字占 3 个字节(utf8编码)
- 一个汉字占 2 个字节(gbk编码)
选择VARCHAR合适的情况
- 字符串列的最大长度比平均长度大很多
- 列的更新很少,所以碎片不是问题
- 使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储
Innodb会把过长的VARCHAR存储为BLOB
CHAR
CHAR类型是定长的:MYSQL总是根据定义的字符串长度分配足够的空间。当存储CHAR值时,MYSQL会删除所有的末尾空格。CHAR值会根据需要采用空格进行填充以方便比较
CHAR适合存储很短的字符串,或所有值都接近同一个长度
选择CHAR合适的情况
- 适合存储MD5值,因为是定长的值
- 短的列,CHAR比VACHAR在存储空间上更有效率。例如:CHAR(1)来存储只有Y和N的值,值需要一个字节,但VARCHAR(1)却需要两个字节,因为还需要记录长度
- 使用CHAR时,由于存储空间都是一次性分配的。从这个角度来讲,不存在碎片的困扰。而使用varchar时,因为存储的长度是可变的,当数据长度在更改前后不一致时,就不可避免地会出现碎片的问题
VARCHAR(100)和VARCHAR(200)
- 更长的列会消耗更多的内存,因为MYSQL通常会分配固定大小的内存块来保存内部值。尤其是使用内存临时表进行排序或操作时会特别糟糕。在利用磁盘临时表进行排序时也同样糟糕。最好是分配真正需要的空间。(假设它们都存储了90个字符的数据,那么它们在磁盘上的存储空间是相同的(硬盘上的存储空间是根据实际字符长度来分配存储空间的)。但对于内存来说,则不是这样的,内存是使用varchar中定义的长度(这里为100或255)的内存块来保存值。)
- 使用索引长度有所不同(Explain查看key_len)
BINARY和VARBINARY
存储的是二进制字符串。存储的是字节码而不是字符
BLOB和TEXT类型
BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符串存储。与其他类型不同,MYSQL把每个BLOB和TEXT值当做一个独立的对象处理。存储引擎在存储时通常会做特殊处理。当BLOB和TEXT值太大时,InnoDB会使用专门的“外部”存储区域来进行存储,此时每个值在行内需要1~4个字节存储一个指针,然后再外部存储区域存储实际的值
BLOB和TEXT之间仅有的不同是BLOB类型存储的是二进制数据,没有排序规则或字符集,而TEXT类型有字符集和排序规则
MYSQL对BLOB和TEXT列进行排序与其他按类型不同:它只对每个列的最前max_sort_length字节而不是整个字符串做排序。
MYSQL不能将BLOB和TEXT列全部长度的字符串进行索引,也不能使用这些索引消除排序
枚举ENUM
枚举可以把一些不重复的字符串存储成一个预定义的集合。MYSQL在存储枚举时非常紧凑,会根据列表值的数量压缩到一个或两个字节中。MYSQL在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的“查找表”
枚举字段是按照内部存储的整数而不是定义的字符串进行排序的,可以使用FIELD()函数指定排序,但这会导致MYSQL无法利用索引消除排序
缺点
字符串列表是固定的,维护成本高,每次增加或修改,都需要使用ALTER TABLE,修改结构,对于未来可能会改变的字符串,使用枚举不是一个好主意
日期和时间类型
DATETIME
范围值:1001-9999年,与时区无关,使用8个字节存储空间
TIMESTAMP
范围值:1970-2038年,使用4个字节的存储空间,TIMESTAMP显示的值依赖于时区。比DATETIME空间效率更高
NULL
NULL列会带来额外的工作。当可为NULL的列被索引时,每个索引记录需要一个额外的字节,在MyISAM里甚至还可能导致固定大小的索引变成可变大小的索引。(例如值有一个整数列的索引)。Innodb使用单独的位(bit)存储NULL值,所以对于稀疏数据有很好的空间效率
MYSQL的数据类型可以存储相同类型的数据,只是存储的长度和范围不一样、允许的精度不同,或需要的物理空间(磁盘和内存空间)不同。