• MySQL知识总结 (一) 数据类型


    mysql数据类型汇总

    分类类型名称说明
    整数类型tinyInt很小的整数(8位二进制)
    smallint小的整数(16位二进制)
    mediumint中等大小的整数(24位二进制)
    int(integer)普通大小的整数(32位二进制)
    BigInt64位
    浮点数类型float单精度浮点数
    double双精度浮点数
    decimal(m,d)压缩严格的定点数,共m位,取d位存储小部分,剩下m-d位存储整数部分
    日期类型yearYYYY 1901~2155
    timeHH:MM:SS -838:59:59~838:59:59
    dateYYYY-MM-DD 1000-01-01~9999-12-3
    datetimeYYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59
    timestampYYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC
    文本、二进制类型CHAR(M)M为0~255之间的整数
    VARCHAR(M)M为0~65535之间的整数
    TINYBLOB允许长度0~255字节
    BLOB允许长度0~65535字节
    MEDIUMBLOB允许长度0~167772150字节
    LONGBLOB允许长度0~4294967295字节
    TINYTEXT允许长度0~255字节
    TEXT允许长度0~65535字节
    MEDIUMTEXT允许长度0~167772150字节
    LONGTEXT允许长度0~4294967295字节
    VARBINARY(M)允许长度0~M个字节的变长字节字符串
    BINARY(M)允许长度0~M个字节的定长字节字符串

    1、整数类型

    包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数。任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的,即非负整数。

    长度:整数类型可以被指定长度,例如:INT(11)表示长度为11的INT类型。长度在大多数场景是没有意义的,它不会限制值的合法范围,只会影响显示字符的个数,而且需要和UNSIGNED ZEROFILL属性配合使用才有意义。

    例子:假定类型设定为INT(5),属性为UNSIGNED ZEROFILL,如果用户插入的数据为12的话,那么数据库实际存储数据为00012。

    2、小数类型

    包括FLOAT、DOUBLE、DECIMAL。

    DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数。而FLOAT和DOUBLE是有取值范围的,并支持使用标准的浮点进行近似计算。计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串进行处理。

    3、字符串类型

    包括VARCHAR、CHAR、TEXT、BLOB

    VARCHAR用于存储可变长字符串,它比定长类型更节省空间。VARCHAR使用额外1或2个字节存储字符串长度。列长度小于255字节时,使用1字节表示,否则使用2字节表示。VARCHAR存储的内容超出设置的长度时,内容会被截断。

    CHAR是定长的,根据定义的字符串长度分配足够的空间。CHAR会根据需要使用空格进行填充方便比较。
    CHAR适合存储很短的字符串,或者所有值都接近同一个长度。CHAR存储的内容超出设置的长度时,内容同样会被截断。

    使用策略:

    1. 对于经常变更的数据来说,CHAR比VARCHAR更好,因为CHAR不容易产生碎片。
    2. 对于非常短的列,CHAR比VARCHAR在存储空间上更有效率。使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存。
    3. 尽量避免使用TEXT/BLOB类型,查询时会使用临时表,导致严重的性能开销。

    4、枚举类型(ENUM)

    把不重复的数据存储为一个预定义的集合。有时可以使用ENUM代替常用的字符串类型。ENUM存储非常紧凑,会把列表值压缩到一个或两个字节。ENUM在内部存储时,其实存的是整数。尽量避免使用数字作为ENUM枚举的常量,因为容易混乱。排序是按照内部存储的整数排序。

    5、日期和时间类型

    默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。

    int(10) 和 bigint(10)能存储的数据大小一样吗?

    不一样,具体原因如下:

    • int 能存储四字节有符号整数。
    • bigint 能存储八字节有符号整数。

    所以能存储的数据大小不一样,其中的数字 10 代表的只是数据的显示宽度。

    • 显示宽度指明Mysql最大可能显示的数字个数,数值的位数小于指定的宽度时数字左边会用空格填充,空格不容易看出。
    • 如果插入了大于显示宽度的值,只要该值不超过该类型的取值范围,数值依然可以插入且能够显示出来。
    • 建表的时候指定 zerofill 选项,则不足显示宽度的部分用 0 填充,如果是 1 会显示成 0000000001。
    • 如果没指定显示宽度, bigint 默认宽度是 20 ,int默认宽度 11。
    • 如果一个数据超过指定的宽度,但是数据大小只要不超过数据类型的最大值依然可以插入成功。

    varchar存储规则

    • 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节)
    • 5.0版本以上,varchar(20),指的是20字符,无论存放的是数字、字母还是UTF8汉字(每个汉字3字节),都可以存放20个,最大的大小是65532字节

    MySQL中varchar最大长度是多少?

    参考文档

    varchar底层

    char和varchar有什么区别?

    区别一,定长和变长:

    char 表示定长,长度固定;varchar表示变长,即长度可变。当所插入的字符串超出它们的长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误信息,如果是宽松模式,则会截取然后插入。如果插入的字符串长度小于定义长度时,则会以不同的方式来处理,如char(10),表示存储的是10个字符,无论你插入的是多少,都是10个,如果少于10个,则用空格填满。而varchar(10),小于10个的话,则插入多少个字符就存多少个。
    varchar怎么知道所存储字符串的长度呢?实际上,对于varchar字段来说,需要使用一个(如果字符串长度小于255)或两个字节(长度大于255)来存储字符串的长度。但是因为他需要有一个prefix来表示他具体bytes数是多少(因为varchar是变长的,没有这个长度值他不知道如何读取数据)。

    区别之二,存储的容量不同:

    对 char 来说,最多能存放的字符个数 255,和编码无关。而 varchar 呢,最多能存放 65532 个字符。VARCHAR 的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节

    Datetime 和 Timestamp 之间抉择

    Datetime 和 Timestamp 是 MySQL 提供的两种比较相似的保存时间的数据类型。他们两者究竟该如何选择呢?

    通常我们都会首选 Timestamp。 下面说一下为什么这样做!

    1. DateTime 类型没有时区信息

    DateTime 类型是没有时区信息的(时区无关) ,DateTime 类型保存的时间都是当前会话所设置的时区对应的时间。这样就会有什么问题呢?当你的时区更换之后,比如你的服务器更换地址或者更换客户端连接时区设置的话,就会导致你从数据库中读出的时间错误。不要小看这个问题,很多系统就是因为这个问题闹出了很多笑话。

    Timestamp 和时区有关。 Timestamp 类型字段的值会随着服务器时区的变化而变化,自动换算成相应的时间,说简单点就是在不同时区,查询到同一个条记录此字段的值会不一样。 下面实际演示一下! 建表 SQL 语句:

    建表SQL语句:

    CREATE TABLE `time_zone_test` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `date_time` datetime DEFAULT NULL,
      `time_stamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    插入数据

    INSERT INTO time_zone_test(date_time,time_stamp) VALUES(NOW(),NOW());
    
    
    • 1
    • 2

    查看数据

    select date_time,time_stamp from time_zone_test;
    
    
    • 1
    • 2

    结果
    在这里插入图片描述

    修改当前会话的时区

    set time_zone = '+10:00'
    
    • 1

    再次查看数据

    在这里插入图片描述

    扩展:一些关于 MySQL 时区设置的一个常用 sql 命令

    # 查看当前会话时区
    SELECT @@session.time_zone;
    # 设置当前会话时区
    SET time_zone = 'Europe/Helsinki';
    SET time_zone = "+00:00";
    # 数据库全局时区设置
    SELECT @@global.time_zone;
    # 设置全局时区
    SET GLOBAL time_zone = '+8:00';
    SET GLOBAL time_zone = 'Europe/Helsinki';
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. DateTime 类型耗费空间更大

    Timestamp 只需要使用 4 个字节的存储空间,但是 DateTime 需要耗费 8 个字节的存储空间。但是,这样同样造成了一个问题,Timestamp 表示的时间范围更小。

    • DateTime :1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
    • Timestamp: 1970-01-01 00:00:01 ~ 2037-12-31 23:59:59

    Timestamp 在不同版本的 MySQL 中有细微差别。

    3. 数值型时间戳是更好的选择吗?

    很多时候,我们也会使用 int 或者 bigint 类型的数值也就是时间戳来表示时间。

    这种存储方式的具有 Timestamp 类型的所具有一些优点,并且使用它的进行日期排序以及对比等操作的效率会更高,跨系统也很方便,毕竟只是存放的数值。缺点也很明显,就是数据的可读性太差了,你无法直观的看到具体时间。

    数据库中实际操作:

    mysql> select UNIX_TIMESTAMP('2020-01-11 09:53:32');
    +---------------------------------------+
    | UNIX_TIMESTAMP('2020-01-11 09:53:32') |
    +---------------------------------------+
    |                            1578707612 |
    +---------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> select FROM_UNIXTIME(1578707612);
    +---------------------------+
    | FROM_UNIXTIME(1578707612) |
    +---------------------------+
    | 2020-01-11 09:53:32       |
    +---------------------------+
    1 row in set (0.01 sec)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4. 总结

    每种方式都有各自的优势,根据实际场景才是王道。下面再对这三种方式做一个简单的对比,以供大家实际开发中选择正确的存放时间的数据类型。
    在这里插入图片描述

  • 相关阅读:
    《围城》笔记
    Laravel 模型的关联写入&多对多的关联写入 ⑩③
    大数据常见面试题 Hadoop篇(1)
    【学习笔记】指向常量的指针和常量指针
    在Linux/Ubuntu/Debian中使用 `tee` 命令将输出显示在终端并写入文件中
    Docker镜像的配置
    tep完整教程帮你突破pytest
    java毕业生设计亿互游在线平台网站计算机源码+系统+mysql+调试部署+lw
    17C++内存分区模型
    机器学习和深度学习相关指标和方法
  • 原文地址:https://blog.csdn.net/weixin_45773632/article/details/126077541