MySQL中的数据类型

2023-06-15 08:50:12 阅读:785 评论:0 点赞:0
所属分类: MySQL

一、前言

1、更小的数据类型
尽量使用能够正确存储和表示数据的最小数据类型,即更快、占用磁盘、内存、CPU缓存空间更少,CPU处理周期也更少。

2、简单为好
简单数据类型的CPU周期更少。例如,整形数据比字符型数据的比较操作代价更低(字符型的字符集和排序规则使其数据的比较更复杂)。

3、尽量避免存储NULL
因为NULL可以是列的默认值,通常情况下最好将列指定为NOT NULL,除非明确需要存储NULL值。保护NULL值的列,MySQL更难优化(列的索引、索引统计和值比较更复杂),可为NULL的列会占用更多的存储空间;通常把可为NULL的列改为NOT NULL带来的性能提升比较小。

1.1 如何确定数据类型

1、确定适合的大类型:数字、字符串、时间等。
2、选择具体的数据类型;储相同类型的数据,但在存储的值范围、表示的精度或者需要的物理空(磁盘和内存)上存在着差异。相同大类型的不同子数据类型有时也有一些特殊的行为和属性。

例如 DATETIMETIMESAMP 列可以存储相同类型的数据:时间和日期,精确到秒。然而 TIMESTAMP 只使用 DATETIME 一半的存储空间,还会根据时区变化,而且具有特殊的自动更新能力。另一方面,TIMESTAMP 允许的时间范围要小得多,有时候它的特殊能力会成为障碍。

二、整形数据

MySQL中有两种类型的数字:整数和实数(带有小数部分的数字)。

2.1 整数

如果存储整数,可以使用这几种整数类型:TINYINT、SMALLINT、MEDIUMINT、INT或BIGINT。它们分别使用8、16、24、32和64位存储空间。可以存储的值的范围从 -2^(N-1)2^(N-1)-1,其中N是存储空间的位数。

整数类型有可选的 UNSIGNED 属性,表示不允许负值,这大致可以使正数的上限提高一倍。

整数类型的宽度,列如:INT(11),这里不会限制值的合法范围,只是用来显示字符的个数,即对于存储来说 INT(1)INT(20) 是相同的。

2.2 实数

实数是带有小数部分的数字。然而,它们不仅适用于带小数的数字,也可以使用 DECIMAL 存储比 BIGINT 还大的整数。

三、字符串类型

MySQL支持多种字符串数据类型,每种类型还有许多变体。每个字符串列可以有自己的字符集和该字符集的排序规则集。

3.1 varchar 和 char 类型

varcahr
varcahr 用于存储可变长度的字符串,它比固定长度的类型更节省空间,因为它仅使用必要的空间。要额外使用1或2字节记录字符串的长度,列的长度 <=255 字节,则使用1字节表示,否则使用 2 字节表示。

VARCHAR节省了存储空间,所以对性能也有帮助。但是,由于行是可变长度的,在更新时可能会增长,这会导致额外的工作。

char
CHAR是固定长度的:MySQL总是为定义的字符串长度分配足够的空间。当存储CHAR值时,MySQL删除所有尾随空格。如果需要进行比较,值会用空格填充。
CHAR适合存储非常短的字符串,或者适用于所有值的长度都几乎相同的情况。

char 适合存储长度相同,经常修改的数据以及非常短的列。

3.2 BINARY和VARBINARY

它们存储的是二进制字符串。二进制字符串与常规字符串非常相似,但它们存储的是字节而不是字符。填充也不
同:MySQL填充BINANRY用的是\0(零字节)而不是空格,并且在检索时不会去除填充值。

使用 VARCHAR(5)和 VARCHAR(200)存储 ‘hello’ 的空间开销是一样的。

事实证明有很大的优势。较大的列会使用更多的内存,因为MySQL通常会在内部分配固定大小的内存块来保存值。这对于使用内存临时表的排序或操作来说尤其糟糕。在利用磁盘临时表进行文件排序时也同样糟糕。最好的策略是只分配真正需要的空间。

3.3 BLOB和TEXT

BLOBTEXT 都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符
方式存储。
实际上,它们分别属于两组不同的数据类型家族:
字符类型是 TINYTEXTSMALLTEXTTEXTMEDIUMTEXTLONGTEXT
二进制类型是 TINYBLOBSMALLBLOBBLOBMEDIUMBLOBLONGBLOB
BLOBSMALLBLOB 的同义词,TEXTSMALLTEXT 的同义词。

提示

BLOB和TEXT家族之间的唯一区别是,BLOB类型存储的是二进制数据,没有排序规则或字符集,但TEXT类型有字符集和排序规则。

排序依据:
MySQL对BLOB和TEXT列的排序与其他类型不同:它只对这些列的最前 max_sort_length 字节而不是整个字符串做排序。如果只需要按前面少数几个字符排序,可以减小 max_sort_length 服务器变量的值。

注意

MySQL不能将BLOB和TEXT数据类型的完整字符串放入索引,也不能使用索引进行排序。

枚举代替字符串类型
有时可以使用 ENUM(枚举)列代替常规的字符串类型。ENUM 列可以存储一组预定义的不同字符串值。MySQL在存储枚举时非常紧凑,会根据列表值的数量压缩到1或者2字节中。在内部会将每个值在列表中的位置保存为整数。

ENUM(枚举)实际上存储的是整数,而不是字符串。可以通过在数值上下文中检索看到这个双重属性:
788e8428-f473-4519-88e6-a51700687545

注意

ENUM 字段是根据内部整数值排序的,而不是根据字符串本身。

3.4 日期和时间类型

MySQL中有很多数据类型用以支持各种各样的日期和时间值,比如YEAR和DATE。

MySQL可以存储的最小时间粒度是微秒。大多数时间类型都没有其他选择,因此不存在哪一种是最佳选择的问题。唯一的问题是,当需要同时存储日期和时间时该怎么做。MySQL提供了两种非常相似的数据类型来实现这一需求:DATETIMETIMESTAMP

DATETIME
这种类型可以保存大范围的数值,从1000年到9999年,精度为1微秒。它以 YYYYMMDDHHMMSS 格式存储压缩成整数的日期和时间,且与时区无关。这需要8字节的存储空间。

默认情况下,MySQL以可排序、无歧义的格式显示 DATETIME 值,例如,2008-01-16 22:37:08。这是ANSI表示日期和时间的标准方式。

TIMESTAMP
TIMESTAMP 类型存储自1970年1月1日格林尼治标准时间(GMT)午夜以来经过的秒数——与UNIX时间戳相同 TIMESTAMP 只使用4字节的存储空间,所以它的范围比 DATETIME 小得多:只能表示从1970年到2038年1月19日。MySQL提供 FROM_UNIXTIME() 函数来将UNIX时间戳转换为日期,并提供了 UNIX_TIMESTAMP() 函数将日期转换为 UNIX 时间戳。时间戳显示的值依赖于时区。MySQL服务器、操作系统和客户端连接都有时区设置。

TIMESTAMP 列在默认情况下为 NOT NULL

3.5 位压缩数据类型

MySQL有几种使用值中的单个位来紧凑地存储数据的类型。所有这些位压缩类型,不管底层存储和处理方式如何,从技术上来说都是字符串类型。

BIT
可以使用BIT列存储一个或多个true/false值。BIT(1)定义一个包含1位的字段,BIT(2)存储2位的字段,依此类推;BIT列的最大长度为64位。InnoDB将每一列存储为足够容纳这些位的最小整数类型,所以使用BIT列不会节省任何存储空间。

MySQL在处理时会将BIT视为字符串类型,而不是数字类型。当检索BIT(1)的值时,结果是一个包含二进制值0或1的字符串,而不是ASCII码的“0”或“1”。但是,如果在数字上下文中检索该值,则会将BIT字符串转换为数字。如果需要将结果与另外的值进行比较,一定要记得这一点。例如,如果将值b’00111001’(二进制数相当于57)存储到BIT(8)列中并检索它,则将得到包含字符码为57的字符串。这恰好是“9”的ASCII字符代码。但在数字上下文场景中,得到的将会是数字57。

SET
如果需要存储多个 true/false 值,可以考虑使用MySQL原生的 SET 数据类型,可以将多列组合成一列,这在MySQL内部是以一组打包的位的集合来表示的。这样可以更有效地利用存储空间,MySQL具有 FIND_IN_SET()FIELD() 等函数,使其易于在查询中使用。

3.6 JSON数据类型

使用JSON作为系统之间交换数据的格式正变得越来越普遍。MySQL有原生的JSON数据类型,可以方便地直接在表中的JSON结构部分进行操作。纯粹主义者可能会认为,在数据库中存储原始JSON是一种反范式,因为理想情况下,schema应该是JSON中具体字段的表示。新手在查看JSON数据类型时,可能会发现这是避免创建和管理独立字段的捷径。

3.7 选择标识符

一般来说,标识符是引用行及通常使其唯一的方式。例如,如果你有一个关于用户的表,可能希望为每个用户分配一个数字ID或唯一的用户名。此字段可能是主键中的部分或全部。

为标识符列选择合适的数据类型非常重要。与其他列相比,更有可能将标识符列与其他值(例如,在联接中)进行比较,并使用它们进行查找。标识符列也可能在其他表中作为外键,因此为标识符列选择数据类型时,应该与联接表中的对应列保持一致。

四、小结

● 尽量避免在设计中出现极端情况,例如,强制执行非常复杂的查询或者包含很多列
的表设计(很多的意思是介于有点多和非常多之间)。
● 使用小的、简单的、适当的数据类型,并避免使用NULL,除非确实是对真实数据
进行建模的正确方法。
● 尝试使用相同的数据类型来存储相似或相关的值,尤其是在联接条件中使用这些值
时。
● 注意可变长度字符串,它可能会导致临时表和排序的全长内存分配不乐观。
● 如果可能的话,尝试使用整数作为标识符。
● 避免使用一些传统的MySQL技巧,例如,指定浮点数的精度或整数的显示宽度。
● 小心使用ENUM和SET类型。它们很方便,但也可能被滥用,有时还很棘手。另外
最好避免使用BIT类型。

标签: mysql 数据类型

永不言弃

职业:后端开发工程师
学校:重庆师范大学
城市:重庆
文章:169
好吧,不知道说点什么...

登录逐梦笔记

注册逐梦笔记

已有账号?