MySQL: datetime vs timestamp

区别

  • datetime支持时间区间 1000-01-01 00:00:009999-12-31 23:59:59timestamp只支持'1970-01-01 00:00:01' UTC'2038-01-19 03:14:07' UTC
  • datetime直接保存不需要转换,timestamp会转变为UTC时间保存在数据库,当select的时候再转变为当前时区的时间
  • datetime存储需要更多的字节,在mysql支持毫秒之前,datetime需要8字节,而timestamp只需要4个字节。细节可以参考TIMESTAMP vs. DATETIME, which should I be using?;支持毫秒之后,存储空间有两次变化,细节参见MySQL: DATETIME vs TIMESTAMP

误解

网上有一些描述存在错误

  • 错误: datetime不支持建立索引,其实是支持的。如下:
person | CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `ctime` (`create_time`),
  KEY `mtime` (`modify_time`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8

最佳实践

datetimetimestamp没有明显的优劣之分,如果选择要看实际场景,这里总结一些自己和别人的经验

  • 如果需要提供全球服务或者跨时区调用,优先选择timestamp;不过如果希望不同时区也显示同一个时间,则使用datetime(看具体应用吧)
  • 时间跨度很大,timestamp满足不了的,只能选择datetime。比如历史时间或者未来时间。

时区对datetimetimestamp的影响

mysql> show create table person;
+--------+---------------------------------------------------------------------------+
| Table  | Create Table |
+--------+---------------------------------------------------------------------------+
| person | CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 |
+--------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

personcreate_time字段是datetime类型,modify_timetimestamp类型

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.06 sec)

mysql> select * from person;
+----+------+---------------------+---------------------+
| id | name | create_time         | modify_time         |
+----+------+---------------------+---------------------+
|  1 | tim  | 2018-07-14 17:42:40 | 2018-07-14 17:42:40 |
+----+------+---------------------+---------------------+
1 row in set (0.00 sec)

可以看出表中的create_timemodify_time的时间都是2018-07-14 17:42:40

mysql> set time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | +00:00 |
+------------------+--------+
2 rows in set (0.00 sec)

mysql> select * from person;
+----+------+---------------------+---------------------+
| id | name | create_time         | modify_time         |
+----+------+---------------------+---------------------+
|  1 | tim  | 2018-07-14 17:42:40 | 2018-07-14 09:42:40 |
+----+------+---------------------+---------------------+
1 row in set (0.00 sec)

如果设置时区为0时区,则可以看到create_time不变,但是modify_time发生了变化,这是因为timestamp的保存是与时区无关的,当显示的时候,则会自动转变为当前时区的时间

注意事项

  • CST:是一个可能代表多个时区的简写,这里是China Standard Time,但是大部分情况下都是代表美国中部标准时间Central Standard Time

参考资料

  • MySQL: DATETIME vs TIMESTAMP
  • TIMESTAMP vs. DATETIME, which should I be using?
  • MySQL Datetime vs Timestamp column types – which one I should use?
  • Mybatis和Mysql的Datetime的一些问题

如果有一点帮助,麻烦点一个赞,如果没有,也期待你的反馈

你可能感兴趣的:(MySQL: datetime vs timestamp)