摘抄自
公众号:码匠笔记警告!别再使用 TIMESTAMP 作为日期字段~
最近根据业务要求,数据库中几乎每张业务表都需要一个日期列,用于记录每条记录产生和变更的时间。日期类型虽然常见,但在表结构设计中却容易犯错,MySQL中提供的日期类型有 YEAR、DATE、TIME、DATETIME、TIMESTAMP。根据业务需求,我们需要将日期精确到秒,所以在表结构设计中,常见使用的日期类型为 DATETIME和TIMESTAMP。下面就深入地了解一下这两种类型以及它们在实际应用中的性能表现。
一.DATETIME
类型DATETIME最终展现的形式为:
YYYY-MM-DD HH:MM:SS
复制
固定占用8个字节。从MySQL 5.6 开始,DATETIME类型支持毫秒,DATETIME(N)中的N表示毫秒的精度。
eg:DATETIME(6)表示可以存储6位的毫秒值。同时,一些日期函数也支持精确到毫秒,例如常见的函数NOW、SYSDATE。
在日常开发中,会遇到用户注册时间/最近修改时间这样的字段,那么就可以利用DATETIME初始化值设置为当前时间,并设置自动更新当前时间的属性。
eg:某业务用户表User有 regi_date(注册时间) last_modi_date(最近修改时间)
create table user(
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
sex CHAR(1) NOT NULL,
regi_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
last_modi_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) on UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(id)
);
复制
其中,
DEFAULT CURRENT_TIMESTAMP
复制
表示记录插入时,若没有指定时间,默认就是当前时间。
DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
复制
表示每次修改都会修改为当前时间。
以上便是 DATETIME 在实际应用中最常用的功能。
二.TIMESTAMP
TIMESTAMP 时间戳,它存储的是 从 '1970-01-01 00:00:00' 到现在的毫秒数。在MySQL中,5.6版本以后,TIMESTAMP开始支持存储毫秒,与DATETIME不同的是,TIMESTAMP会自动伸缩自己占用的字节数,假如设置为支持毫秒,则占用七个字节。否则默认占用四个字节。由上文提及,DATETIME无论存啥都占用8个字节。这是TIMESTAMP的一大优势。
TIMESTAMP可以带时区属性,比如我们要做一个国际性的大服务,涉及了全世界国家的时间需求,且有些国家还会执行夏令时,那么TIMESTAMP都会帮我们解决这个问题。其中,time_zone参数指定了当前使用的时区,默认操作系统的时区。
三.总结
首先说的是,千万不要再用INT类型模拟TIMESTAMP的操作来存日期数据了。因为本质上用INT还是在算当前距离 1970-01-01 00:00:00 的毫秒数,所以是没有意义的。
其次,我们知道TIMESTAMP存储的是毫秒数,显然它是有数据极限的,就算它到了七个字节,它的数据上限也会在 2038 年到来,也许在遥远的16年后我们写的服务都不存在了哈哈。
但如果不得不使用TIMESTAMP的话,建议在mysql配置文件自行添加时区属性,不要使用默认操作系统的时区。
最后,如果不考虑极限性能压榨的情况下,从省事的角度的话,推荐使用DATETIME数据类型。