基于本文回答
0
评论

DATETIME 和 TIMESTAMP 有什么区别?

知识点图片

本文对比了DATETIME和TIMESTAMP。核心区别:DATETIME是时区无关的固定时间;TIMESTAMP是时区相关的UTC时间点,会自动转换。

这是一个在数据库设计中非常经典的问题。DATETIMETIMESTAMP 都用于存储日期和时间,但它们在时区处理、存储空间、取值范围和默认行为上有本质的区别。

简单来说:

  • DATETIME:存储一个固定的、与时区无关的日期和时间。你存入什么,取出来就是什么。
  • TIMESTAMP:存储一个相对于 UTC(世界标准时间)的时间点。它会根据数据库服务器或客户端的时区设置进行转换。

下面我们来详细分解这些区别。


核心区别详解

1. 时区处理(最重要的区别)

  • DATETIME: 时区无关 (Timezone-naive)

    • 它存储的是一个字面上的日期和时间,例如 '2023-10-27 10:00:00'
    • 它不包含任何时区信息。无论你的数据库服务器、操作系统或客户端连接设置在哪个时区,你存入 '2023-10-27 10:00:00',取出来的永远是 '2023-10-27 10:00:00'
    • 比喻:就像在一张纸上写下“10月27日上午10点”。这个记录本身是固定的,不会因为你看这张纸时身处北京还是纽约而改变。
  • TIMESTAMP: 时区相关 (Timezone-aware)

    • 当你存入一个时间时,它会先从你当前会话(Session)的时区转换为 UTC 时间(Coordinated Universal Time,世界标准时间)进行存储。
    • 当你查询这个时间时,它又会从存储的 UTC 时间转换回你当前会话的时区来显示。
    • 比喻:就像记录一个全球性的事件瞬间。比如,一个用户在北京时间(UTC+8)2023-10-27 10:00:00 发布了一篇文章,数据库会将它转换成 UTC 时间 2023-10-27 02:00:00 存储。当一个在东京(UTC+9)的用户查看时,他看到的时间是 2023-10-27 11:00:00。虽然显示的具体时间不同,但它们都指向同一个历史瞬间。

2. 取值范围

  • DATETIME: 范围非常广。

    • 通常是 '1000-01-01 00:00:00''9999-12-31 23:59:59'
    • 适合存储需要久远历史或未来日期的信息,如出生日期、历史事件等。
  • TIMESTAMP: 范围相对较小。

    • 它存储的是自 Unix 纪元(1970-01-01 00:00:00 UTC)以来的秒数。
    • 在32位系统中,其范围是 '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC。这就是著名的 “2038年问题”(Y2K38 problem)。
    • 虽然现在很多系统是64位的,解决了这个问题,但在设计时仍需考虑兼容性。

3. 存储空间

  • DATETIME: 存储空间通常较大。

    • 在 MySQL 5.6.4 之前,固定占用 8个字节
    • 在 MySQL 5.6.4 及之后,它被优化为 5个字节 + 小数秒的额外字节。
  • TIMESTAMP: 存储空间较小。

    • 固定占用 4个字节 + 小数秒的额外字节。
    • 由于它存储的是一个整数(秒数),所以更节省空间。

4. 自动更新特性(以 MySQL 为例)

  • DATETIME:

    • 在旧版本的 MySQL 中,DATETIME 字段需要手动设置或更新。
    • 从 MySQL 5.6.5 开始,DATETIME 也可以像 TIMESTAMP 一样设置 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP
  • TIMESTAMP:

    • 这是 TIMESTAMP 的一个经典特性。默认情况下,如果你不给 TIMESTAMP 字段赋值,它会自动设置为当前时间。
    • 你还可以定义 ON UPDATE CURRENT_TIMESTAMP,这样每当这一行数据被更新时,该字段的值就会自动更新为当前的系统时间。这使得它非常适合用作 created_atupdated_at 这样的字段。

对比总结表

特性 DATETIME TIMESTAMP
时区处理 与时区无关,存储字面值 与时区相关,存储为 UTC,按会话时区显示
取值范围 宽 (1000 ~ 9999 年) 窄 (1970 ~ 2038 年,32位系统)
存储空间 较大 (5~8 字节) 较小 (4 字节)
自动更新 新版支持,但非传统特性 核心特性,常用于 created_at, updated_at
NULL 值 允许 允许(但如果不允许,会自动设为当前时间)

我应该用哪个?(选择建议)

选择 DATETIME 的场景:

  1. 存储一个固定的、不应随地域变化的时间。
    • 例如:用户的生日、法定节假日、特定活动的开始时间(如“北京时间晚上8点开始”)。这些时间点是明确的,不应该因为服务器换了地方或用户在不同时区查看而改变。
  2. 需要存储 1970 年以前或 2038 年以后的日期。
    • 例如:历史事件记录、长期的合同到期日等。

选择 TIMESTAMP 的场景:

  1. 构建国际化应用,需要为不同时区的用户正确显示时间。
    • 例如:文章发布时间、消息发送时间、订单创建时间。全球用户看到的应该是他们本地时区的对应时间。
  2. 记录数据的创建或最后修改时间。
    • 例如:created_atupdated_at 字段。TIMESTAMP 的自动更新特性完美契合这个需求。
  3. 对存储空间敏感的场景。
    • TIMESTAMP 更节省空间。

总之,记住这个核心原则:如果你的时间是针对一个全球性的“时刻”,用 TIMESTAMP;如果你的时间是针对一个日历上的“标记”,用 DATETIME

右滑查看面试常问