日期类型

日期类型 占用空间(字节数) 表示范围
date 4 1000-01-01 ~ 9999-12-31
datetime 8 1000-01-01 00:00:00.000000 ~ 9999-12-31 23:59:59.999999
timestamp 4 1970-01-01 00:00:00.000000UTC ~ 2038-01-19 03:14:07.000000UTC
year 1 1901-2155
time 3 -838:59:59.000000 ~ 838:59:59.000000

datetime

从MySQL5.6版本开始,DATETIME类型支持毫秒,DATETIME(N)中的N表示毫秒的精度。例如,DATETIME(6)表示可以存储6位的毫秒值。同时,一些日期函数也支持精确到毫秒,例如常见的函数 NOW、SYSDATE:

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-05-15 17:33:09 |
+---------------------+
1 row in set (0.01 sec)mysql> select now(6);
+----------------------------+
| now(6)                     |
+----------------------------+
| 2021-05-15 17:33:19.068396 |
+----------------------------+
1 row in set (0.00 sec)

用户可以将DATETIME初始化值设置为当前时间,并设置自动更新当前时间的属性。例如数据库的每个表都会有一个字段create_time来都会记录创建时间,使用update_time来记录这条记录每次修改的时间。

mysql> show create table user;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                      |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user  | CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL,`create_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),`update_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)mysql> insert into user(name) values('morris');
Query OK, 1 row affected (0.01 sec)mysql> select * from user;
+----+--------+----------------------------+----------------------------+
| id | name   | create_time                | update_time                |
+----+--------+----------------------------+----------------------------+
|  1 | morris | 2021-05-15 17:40:00.332704 | 2021-05-15 17:40:00.332704 |
+----+--------+----------------------------+----------------------------+
1 row in set (0.00 sec)mysql> update user set name='marry' where id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from user;
+----+-------+----------------------------+----------------------------+
| id | name  | create_time                | update_time                |
+----+-------+----------------------------+----------------------------+
|  1 | marry | 2021-05-15 17:40:00.332704 | 2021-05-15 17:40:19.785901 |
+----+-------+----------------------------+----------------------------+
1 row in set (0.00 sec)

在上面的表User中,列create_time表示创建时间,DEFAULT CURRENT_TIMESTAMP表示记录插入时,若没有指定时间,默认就是当前时间。列update_time表示当前记录最后的修改时间,DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) 表示每次修改都会修改为当前时间。

在做表结构设计规范时,强烈建议你每张业务核心表都增加一个DATETIME类型的update_time字段,并设置修改自动更新机制,方便标识每条记录最后修改的时间,这样在数据库的同步时也可以利用到这个字段。

TIMESTAMP

除了DATETIME,日期类型中还有一种TIMESTAMP的时间戳类型,其实际存储的内容为‘1970-01-01 00:00:00’到现在的毫秒数。在MySQL中,由于类型TIMESTAMP占用4个字节,因此其存储的时间上限只能到‘2038-01-19 03:14:07’。

同类型DATETIME一样,从MySQL 5.6版本开始,类型TIMESTAMP也能支持毫秒。与DATETIME不同的是,若带有毫秒时,类型TIMESTAMP占用7个字节,而DATETIME无论是否存储毫秒信息,都占用8个字节。

类型TIMESTAMP最大的优点是可以带有时区属性,因为它本质上是从毫秒转化而来。如果你的业务需要对应不同的国家时区,那么类型TIMESTAMP是一种不错的选择。比如新闻类的业务,通常用户想知道这篇新闻发布时对应的自己国家时间,那么TIMESTAMP是一种选择。

另外,有些国家会执行夏令时。根据不同的季节,人为地调快或调慢1个小时,带有时区属性的TIMESTAMP类型本身就能解决这个问题。

参数time_zone指定了当前使用的时区,默认为SYSTEM使用操作系统时区,用户可以通过该参数指定所需要的时区。

如果想使用TIMESTAMP的时区功能,你可以通过下面的语句将之前的用户表User的创建时间字段类型从DATETIME(6)修改为TIMESTAMP(6):

mysql> alter table user change create_time create_time timestamp(6) not null default current_timestamp(6);
Query OK, 1 row affected (3.07 sec)
Records: 1  Duplicates: 0  Warnings: 0

这时通过设定不同的 time_zone,可以观察到不同时区下的注册时间:

mysql> select @@time_zone;
+-------------+
| @@time_zone |
+-------------+
| SYSTEM      |
+-------------+
1 row in set (0.00 sec)mysql> select * from user;
+----+-------+----------------------------+----------------------------+
| id | name  | create_time                | update_time                |
+----+-------+----------------------------+----------------------------+
|  1 | marry | 2021-05-15 17:40:00.332704 | 2021-05-15 17:40:19.785901 |
+----+-------+----------------------------+----------------------------+
1 row in set (0.00 sec)mysql> set time_zone='-08:00';
Query OK, 0 rows affected (0.00 sec)mysql> select * from user;
+----+-------+----------------------------+----------------------------+
| id | name  | create_time                | update_time                |
+----+-------+----------------------------+----------------------------+
|  1 | marry | 2021-05-15 01:40:00.332704 | 2021-05-15 17:40:19.785901 |
+----+-------+----------------------------+----------------------------+
1 row in set (0.00 sec)

从上述例子中,你可以看到,中国的时区是+08:00,美国的时区是-08:00,因此改为美国时区后,可以看到用户注册时间比之前延迟了16个小时。当然了,直接加减时区并不直观,需要非常熟悉各国的时区表。在MySQL中可以直接设置时区的名字,如:

mysql> set time_zone='America/Los_Angeles';
Query OK, 0 rows affected (0.01 sec)mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-05-15 03:09:53 |
+---------------------+
1 row in set (0.00 sec)mysql> set time_zone='Asia/Shanghai';
Query OK, 0 rows affected (0.00 sec)mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2021-05-15 18:10:39 |
+---------------------+
1 row in set (0.00 sec)

在上面设置时区的名字时可能会报如下错误:

mysql> set time_zone='America/Los_Angeles';
ERROR 1298 (HY000): Unknown or incorrect time zone: 'America/Los_Angeles'

这时需要安装timezone的表,可以到http://dev.mysql.com/downloads/timezones.html下载对应版本与系统的sql语句,一般是下载posix标准的那张表,下载完后然后导入到mysql的mysql库中:

mysql> use mysql
Database changedmysql> source /root/timezone_posix.sql
... ...
Query OK, 3214 rows affected, 1 warning (0.14 sec)
Records: 3214  Duplicates: 0  Warnings: 1

DATETIME vs TIMESTAMP vs INT,怎么选?

在做表结构设计时,对日期字段的存储,开发人员通常会有3种选择:DATETIME、TIMESTAMP、INT。

INT类型就是直接存储’1970-01-01 00:00:00’到现在的毫秒数,本质和TIMESTAMP一样,因此用INT不如直接使用TIMESTAMP。

当然,有些同学会认为INT比TIMESTAMP性能更好。但是,由于当前每个CPU每秒可执行上亿次的计算,所以无须为这种转换的性能担心。更重要的是,在后期运维和数据分析时,使用INT存储日期,是会让DBA和数据分析人员发疯的,INT的可运维性太差。

也有的同学会热衷用类型 TIMESTEMP 存储日期,因为类型 TIMESTAMP 占用 4 个字节,比 DATETIME 小一半的存储空间。

但若要将时间精确到毫秒,TIMESTAMP要7个字节,和DATETIME 8字节差不太多。另一方面,现在距离TIMESTAMP的最大值‘2038-01-19 03:14:07’已经很近,这是需要开发同学好好思考的问题。

总的来说,我建议你使用类型DATETIME。对于时区问题,可以由前端或者服务这里做一次转化,不一定非要在数据库中解决。

不要忽视TIMESTAMP的性能问题

虽然从毫秒数转换到类型TIMESTAMP本身需要的CPU指令并不多,这并不会带来直接的性能问题。但是如果使用默认的操作系统时区,则每次通过时区计算时间时,要调用操作系统底层系统函数 __tz_convert(),而这个函数需要额外的加锁操作,以确保这时操作系统时区没有修改。所以,当大规模并发访问时,由于热点资源竞争,会产生两个问题。

  • 性能不如 DATETIME:DATETIME不存在时区转化问题。

  • 性能抖动: 海量并发时,存在性能抖动问题。

为了优化TIMESTAMP的使用,强烈建议你使用显式的时区,而不是操作系统时区。比如在配置文件中显示地设置时区,而不要使用系统时区:

[mysqld]
default-time-zone = '+8:00'

最后,通过命令mysqlslap来测试TIMESTAMP设置时区与不设置的性能,命令如下:

不设置时区,采用默认时区SYSTEM:

# mysqlslap -uroot --number-of-queries=1000000 --concurrency=100 --query='SELECT NOW()' -p
Enter password:
BenchmarkAverage number of seconds to run all queries: 29.898 secondsMinimum number of seconds to run all queries: 29.898 secondsMaximum number of seconds to run all queries: 29.898 secondsNumber of clients running queries: 100Average number of queries per client: 10000

在my.inf文件中指定时区:

# mysqlslap -uroot --number-of-queries=1000000 --concurrency=100 --query='SELECT NOW()' -p
Enter password:
BenchmarkAverage number of seconds to run all queries: 27.597 secondsMinimum number of seconds to run all queries: 27.597 secondsMaximum number of seconds to run all queries: 27.597 secondsNumber of clients running queries: 100Average number of queries per client: 10000

从运行结果中可以发现,显式指定时区的性能要远远好于直接使用操作系统时区。所以,日期字段推荐使用DATETIME,没有时区转化。即便使用 TIMESTAMP,也需要在数据库中显式地配置时区,而不是用系统时区。

MySQL数据类型之日期型相关推荐

  1. mysql decimal型转化为float_5分钟搞懂MySQL数据类型之数值型DECIMAL类型

    速成指南 5分钟搞懂MySQL数据类型 之数值型--DECIMAL类型 DECIMAL类型的语法:DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL].其中M指定的是数字的总位 ...

  2. MySQL数据类型之数值型

    整型 类型 占用字节数 最小值~最大值(有符号) 最小值~最大值(无符号) tinyint 1 -128~127 0~255 smallint 2 -215~215-1 0~2^16-1 medium ...

  3. MySQL数据类型之字符型

    字符类型 类型 说明 N的含义 是否有字符集 最大长度 char(n) 定长字符 字符 是 255 varchar(n) 变长字符 字符 是 65535 binary(n) 定长二进制字节 字节 否 ...

  4. mysql数据类型查询命令_Linux命令:MySQL系列之三--mysql数据类型及SQL结构化查询语句使用...

    MySQL 存储引擎,也被称为表类型: MyISAM表:无事务处理功能,支持表锁 .frm:表结构定义文件 .MYD:表数据文件 .MYI:表索引文件 InnoDB表:支持事务处理功能,支持行锁 .f ...

  5. 二、mysql数据类型

    二.mysql数据类型 1.数值型 decimal(65) decimal最大支持65位 bit(10) 最大支持10位的二进制存储模式 bin(column),hex(column) 使用bin(二 ...

  6. MySQL数据类型 -- 日期时间型

    在MySQL关系型数据库中,MySQL支持的数据类型非常丰富.它主要分为3大类,即:数值型,日期时间性,字符型.而实际上这三类数据类型可以进一步的细分扩展,可以根据业务需要选择最适合的一种.本文主要介 ...

  7. 八、一篇文章快速搞懂MySQL 常见的数据类型(整型、小数、字符型、日期型详解)

    常见的数据类型 1.数值型: 整型 小数: 定点数 浮点数 2.字符型: 较短的文本:char.varchar 较长的文本:text.blob(较长的二进制数据) 3.日期型: 一.整型 1)分类: ...

  8. js获取mysql数据库数据类型_怎么利用JS将从数据库中读取出来的日期型格式化为想要的类型...

    在页面初始化时,用JavaScript将从数据库中读取出来的日期型格式化为想要的类型.格式化为yyyy年MM月dd日 HH时mm分ss秒,大家可以参考下代码,自由发挥下. 代码如下://传入从数据库中 ...

  9. MySQL数据类型--日期时间

    作者:壹叶随风 一.博客前言 自接触学习MySQL已有一段时间了,对于MySQL的基础知识还是有一定的了解的.在这一路学习过来,每次不管看书还是网上看的资料,对于MySQL数据类型中的时间日期类型总是 ...

最新文章

  1. ros-kinetic install error: sudo rosdep init ImportError: No module named 'rosdep2'
  2. Google Guava –期货
  3. lucene 高亮显示
  4. Python使用秦九韶算法求解多项式的值
  5. html元素自己属性代码,jQuery如何操作HTML的元素和属性?(代码详解例)
  6. FTP服务器的搭建及创建虚拟用户进行认证访问
  7. 位置采集[置顶] iPhone手机上的GPS位置信息采集与分享应用
  8. linux 路由添加
  9. json react 展示工具_基于jsoneditor二次封装一个可实时预览的json编辑器组件(react版)...
  10. 敏捷开发框架—Scrum
  11. 直通车推广:打造潮流女装爆款
  12. 一级指针, 二级指针
  13. 小米10pro第二个摄像头下面_小米10 Pro拍照翻车?暂不支持超广角超级夜景,官方回应...
  14. Apple现行公开的framework简介
  15. three.js贴图之CubeTextureLoader全景贴图
  16. 微电影拍摄制作的基本流程有哪些?
  17. 转:条件变量(Condition Variables)
  18. excel报表导入失败问题记录
  19. 相控阵天线(六):直线阵列天线特殊综合方法(变形泰勒综合法、贝利斯综合法、伍德沃德抽样法)
  20. 可将视频转换成Gif动画的相关软件

热门文章

  1. 数组与类数组以及在类数组对象使用数组的方法
  2. 一封黑客写给黑客的信
  3. 中兴交换机怎么查看服务器,中兴交换机查看端口状态命令
  4. ospf综合实验配置
  5. jQuery取消绑定事件 单个事件 单个函数
  6. 蓝桥阿尔法乘积 JAVA暴解
  7. centos 彻底卸载docker
  8. Docker镜像及容器基本操作命令
  9. proxmark3 复制 M1 卡和 CUID卡的方法
  10. 生活随笔:猎场的感悟