| 类型 | 类型举例 |
|---|---|
| 整数类型 | TINYINT、SMALLINT、MEDIUMINT、INT(或INTEGER)、BIGINT |
| 浮点类型 | FLOAT、DOUBLE |
| 定点数类型 | DECIMAL |
| 位类型 | BIT |
| 日期时间类型 | YEAR、TIME、DATE、DATETIME、TIMESTAMP |
| 文本字符串类型 | CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT |
| 枚举类型 | ENUM |
| 集合类型 | SET |
| 二进制字符串类型 | BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB |
| JSON类型 | JSON对象、JSON数组 |
| 空间数据类型 | 单值类型:GEOMETRY、POINT、LINESTRING、POLYGON; 集合类型:MULTIPONINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION; |
| 整数类型 | 字节 | 有符号数取值范围 | 无符号数取值范围 | 适用场景 |
|---|---|---|---|---|
| TININT | 1 | -128~127 | 0~255 | 一般用于枚举数据,比如系统设定取值范围很小且固定的场景 |
| SMALLINT | 2 | -32768~32767 | 0~65535 | 可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等 |
| MEDIUMENT | 3 | -8388608~8388607 | 0~16777215 | 用于较大整数的计算,比如车站每日的客流量等 |
| INT、INTEGER | 4 | -2147483648~2147483647 | 0~4294967295 | 取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号 |
| BIGINT | 8 | -9223372036854775808~9223372036854775807 | 0~18446744073709551615 | 只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等 |
M : 表示显示宽度,M的取值范围是(0, 255)。例如,int(5):当数据宽度小于5位的时候在数字前面需要用字符填满宽度。该项功能需要配合“ ZEROFILL ”使用,表示用“0”填满宽度,否则指定显示宽度无效。
如果设置了显示宽度,那么插入的数据宽度超过显示宽度限制,会不会截断或插入失败?
答案:不会对插入的数据有任何影响,还是按照类型的实际宽度进行保存,即 显示宽度与类型可以存储的值范围无关 。从MySQL 8.0.17开始,整数数据类型不推荐使用显示宽度属性
选用类型标准:
在实际工作中,系统故障产生的成本远远超过增加几个字段存储空间所产生的成本。因此,我建议你首先确保数据不会超过取值范围,在这个前提之下,再去考虑如何节省存储空间
从MySQL 8.0.17开始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用,将来可能被移除。另外,关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了,将来也可能被移除
浮点数类型有个缺陷,就是不精准。
MySQL 用 4 个字节存储 FLOAT 类型数据,用 8 个字节来存储 DOUBLE 类型数据。无论哪个,都是采用二进制的方式来进行存储的。比如 9.625,用二进制来表达,就是 1001.101,或者表达成 1.001101×2^3。如果尾数不是 0 或 5(比如 9.624),你就无法用一个二进制数来精确表达。进而,就只好在取值允许的范围内进行四舍五入。
在编程中,如果用到浮点数,要特别注意误差问题,因为浮点数是不准确的,所以我们要避免使用“=”来判断两个数是否相等。同时,在一些对精确度要求较高的项目中,千万不要使用浮点数,不然会导致结果错误,甚至是造成不可挽回的损失。那么,MySQL 有没有精准的数据类型呢?当然有,这就是定点数类型: DECIMAL
| 定点数类型 | 字节 | 取值范围 |
|---|---|---|
| DECIMAL(M,D) | M+2字节 | 有效范围由M和D决定 |
字符串 的形式进行存储,这就决定了它一定是精准的BIT类型中存储的是二进制值,类似010110
| 二进制字符串类型 | 长度 | 取值范围 | 占用空间 |
|---|---|---|---|
| DECIMAL(M,D) | M(默认1) | 1<=M<=64 | 约为(M + 7)/8个字节 |
| 类型 | 表示 | 长度(字节) | 格式 | 表示范围 |
|---|---|---|---|---|
| YEAR | 年 | 1 | YYYY或YY | 1901~2155 |
| TIME | 时间 | 3 | HH:MM:SS | -838:59:59~838:59:59 |
| DATE | 日期 | 3 | YYYY-MM-SS | 1000-01-01~9999-12-03 |
| DATETIME | 日期 时间 | 8 | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00~9999-12-31 23:59:59 |
| TIMESTAMP | 日期 时间 | 4 | YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:00 UTC~2038-01-19 03:14:07 UTC |
为什么时间类型 TIME 的取值范围不是 -23:59:59~23:59:59 呢?原因是 MySQL 设计的 TIME 类型,不光表示一天之内的时间,而且可以用来表示一个时间间隔,这个时间间隔可以超过 24 小时
从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”,没必要写成YEAR(4),
从MySQL 8.0.19开始,不推荐使用指定显示宽度的YEAR(4)数据类型
TIMESTAMP类型也可以表示日期时间,其显示格式与DATETIME类型相同,都是 YYYY-MM-DD HH:MM:SS ,需要4个字节的存储空间。但是TIMESTAMP存储的时间范围比DATETIME要小很多,只能存储“1970-01-01 00:00:01 UTC”到“2038-01-19 03:14:07 UTC”之间的时间。其中,UTC表示世界统一时间,也叫作世界标准时间
在实际项目中,尽量用 DATETIME 类型。因为这个数据类型包括了完整的日期和时间信息,取值范围也最大,使用起来比较方便。毕竟,如果日期时间信息分散在好几个字段,很不容易记,而且查询的时候,SQL 语句也会更加复杂
| 文本字符串类型 | 值的长度 | 长度范围 | 占用的存储空间 |
|---|---|---|---|
| CHAR(M) | M | 0<=M<=255 | M个字节 |
| VARCHAR(M) | M | 0<=M<=65535 | M+1个字节 |
| TINYTEXT | L | 0<=L<=255 | L+2个字节 |
| TEXT | L | 0<=L<=65535 | L+2个字节 |
| MEDIUMTEXT | L | 0<=L<=16777215 | L+3个字节 |
| LONGTEXT | L | 0<=L<=4294967295 | L+4个字节 |
| ENUM | L | 1<=L<=65535 | 1或2个字节 |
| SET | L | 0<=L<=64 | 1,2,3,4或8个字节 |
| 字符串类型 | 特点 | 长度 | 占用的存储空间 | 占用的存储空间 |
|---|---|---|---|---|
| CHAR(M) | 固定长度 | M | 0<=M<=255 | M个字节 |
| VARCHAR(M) | 可变长度 | M | 0<=M<=65535 | (实际长度+1)个字节 |
哪些情况使用 CHAR 或 VARCHAR 更好
| 类型 | 特点 | 空间上 | 时间上 | 适用场景 |
|---|---|---|---|---|
| CHAR(M) | 固定长度 | 浪费存储空间 | 效率高 | 存储不大,速度要求高 |
| VARCHAR(M) | 可变长度 | 节省存储空间 | 效率低 | 非CHAR的情况 |
MyISAM 数据存储引擎和数据列:MyISAM数据表,最好使用固定长度(CHAR)的数据列代替可变长度(VARCHAR)的数据列。这样使得整个表静态化,从而使数据检索更快 ,用空间换时间MEMORY 存储引擎和数据列:MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没有关系,两者都是作为CHAR类型处理的InnoDB 存储引擎,建议使用VARCHAR类型。因为对于InnoDB数据表,内部的行存储格式并没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),而且主要影响性能的因素是数据行使用的存储总量,由于char平均占用的空间多于varchar,所以除了简短并且固定长度的,其他考虑varchar。这样节省空间,对磁盘I/O和数据存储总量比较好| 文本字符串类型 | 值的长度 | 长度范围 | 占用的存储空间 | 特点 |
|---|---|---|---|---|
| TINYTEXT | L | 0<=L<=255 | L+2个字节 | 小文本、可变长度 |
| TEXT | L | 0<=L<=65535 | L+2个字节 | 文本、可变长度 |
| MEDIUMTEXT | L | 0<=L<=16777215 | L+3个字节 | 中等文本、可变长度 |
| LONGTEXT | L | 0<=L<=4294967295 | L+4个字节 | 大文本、可变长度 |
不推荐使用
和枚举类似,用的较少,故暂时跳过,待未来有需求时再考虑深入研究
BINARY和VARBINARY类似于CHAR和VARCHAR,只是它们存储的是二进制字符串
| 二进制字符串类型 | 特点 | 值的长度 | 占用空间 |
|---|---|---|---|
| BINARY(M) | 固定长度 | M(0<=M<=255) | M个字节 |
| VARBINARY(M) | 可变长度 | M(0<=M<=65535) | M+1个字节 |
MySQL中的BLOB类型包括TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB 4种类型,它们可容纳值的最大长度不同。可以存储一个二进制的大对象,比如 图片 、 音频 和 视频 等
需要注意的是,在实际工作中,往往不会在MySQL数据库中使用BLOB类型存储大对象数据,通常会将图片、音频和视频文件存储到 服务器的磁盘上 ,并将图片、音频和视频的访问路径存储到MySQL中
| 二进制字符串类型 | 值的长度 | 长度范围 | 占用的存储空间 |
|---|---|---|---|
| TINYBLOB | L | 0 <= L <= 255 | L + 1 个字节 |
| BLOB | L | 0 <= L <= 65535(相当于64KB) | L + 2 个字节 |
| MEDIUMBLOB | L | 0 <= L <= 16777215 (相当于16MB) | L + 3 个字节 |
| LONGBLOB | L | 0 <= L <= 4294967295(相当于4GB) | L + 4 个字节 |
碎片整理前缀索引 。但是仍然要在不必要的时候避免检索大型的BLOB或TEXT值分离到单独的表 中。在某些环境中,如果把这些数据列移动到第二张数据表中,可以让你把原数据表中的数据列转换为固定长度的数据行格式,那么它就是有意义的。这会 减少主表中的碎片 ,使你得到固定长度数据行的性能优势。它还使你在主数据表上运行 SELECT * 查询的时候不会通过网络传输大量的BLOB或TEXT值不推荐使用,需要使用的话可以使用非关系型数据库如MongoDB/Redis
MySQL 空间类型扩展支持地理特征的生成、存储和分析。这里的地理特征表示世界上具有位置的任何东西,可以是一个实体,例如一座山;可以是空间,例如一座办公楼;也可以是一个可定义的位置,例如一个十字路口等等。MySQL中使用 Geometry(几何) 来表示所有地理特征。Geometry指一个点或点的集合,代表世界上任何具有位置的事物
未使用到,且不具有普遍性,暂不深入