狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

SQL 數據庫設計儲存表時日期時間字段類型 DATETIME 和 TIMESTAMP 的選擇

admin
2025年6月3日 9:12 本文熱度 688

一、不要用字符串存儲日期


和許多數據庫初學者一樣,筆者在早期學習階段也曾嘗試使用字符串(如 VARCHAR)類型來存儲日期和時間,甚至一度認為這是一種簡單直觀的方法。畢竟,'YYYY-MM-DD HH:MM:SS' 這樣的格式看起來清晰易懂。


但是,這是不正確的做法,主要會有下面兩個問題:

1、空間效率:與 MySQL 內建的日期時間類型相比,字符串通常需要占用更多的存儲空間來表示相同的時間信息。

2、查詢與計算效率低下:

  • 比較操作復雜且低效:基于字符串的日期比較需要按照字典序逐字符進行,這不僅不直觀(例如,'2024-05-01' 會小于 '2024-1-10'),而且效率遠低于使用原生日期時間類型進行的數值或時間點比較。

  • 計算功能受限無法直接利用數據庫提供的豐富日期時間函數進行運算(例如,計算兩個日期之間的間隔、對日期進行加減操作等),需要先轉換格式,增加了復雜性。

  • 索引性能不佳:基于字符串的索引在處理范圍查詢(如查找特定時間段內的數據)時,其效率和靈活性通常不如原生日期時間類型的索引。

?

二、DATETIME 和 TIMESTAMP 選擇


DATETIME 和 TIMESTAMP 是 MySQL 中兩種非常常用的、用于存儲包含日期和時間信息的數據類型。它們都可以存儲精確到秒(MySQL 5.6.4+ 支持更高精度的小數秒)的時間值。那么,在實際應用中,我們應該如何在這兩者之間做出選擇呢?


下面我們從幾個關鍵維度對它們進行對比:


1、時區信息


DATETIME 類型存儲的是字面量的日期和時間值,它本身不包含任何時區信息。當你插入一個 DATETIME 值時,MySQL 存儲的就是你提供的那個確切的時間,不會進行任何時區轉換。


這樣就會有什么問題呢? 如果你的應用需要支持多個時區,或者服務器、客戶端的時區可能發生變化,那么使用 DATETIME 時,應用程序需要自行處理時區的轉換和解釋。如果處理不當(例如,假設所有存儲的時間都屬于同一個時區,但實際環境變化了),可能會導致時間顯示或計算上的混亂。


TIMESTAMP 和時區有關。存儲時,MySQL 會將當前會話時區下的時間值轉換成 UTC(協調世界時)進行內部存儲。當查詢 TIMESTAMP 字段時,MySQL 又會將存儲的 UTC 時間轉換回當前會話所設置的時區來顯示。


這意味著,對于同一條記錄的 TIMESTAMP 字段,在不同的會話時區設置下查詢,可能會看到不同的本地時間表示,但它們都對應著同一個絕對時間點(UTC 時間)。這對于需要全球化、多時區支持的應用來說非常有用。


下面實際演示一下!


建表 SQL 語句:

CREATE TABLE`time_zone_test` (`id`bigint(20NOTNULL AUTO_INCREMENT,`date_time` datetime DEFAULTNULL,`time_stamp`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,  PRIMARY KEY (`id`)ENGINE=InnoDBDEFAULTCHARSET=utf8;


插入一條數據(假設當前會話時區為系統默認,例如 UTC+0):

INSERT INTO time_zone_test(date_time,time_stamp) VALUES(NOW(),NOW());


查詢數據(在同一時區會話下):

SELECT date_time, time_stamp FROM time_zone_test;


結果:

+---------------------+---------------------+| date_time           | time_stamp          |+---------------------+---------------------+| 2020-01-11 09:53:32 | 2020-01-11 09:53:32 |+---------------------+---------------------+


現在,修改當前會話的時區為東八區 (UTC+8):

SET time_zone = '+8:00';


再次查詢數據:

TIMESTAMP 的值自動轉換為 UTC+8 時間+---------------------+---------------------+| date_time           | time_stamp          |+---------------------+---------------------+| 2020-01-11 09:53:32 | 2020-01-11 17:53:32 |+---------------------+---------------------+


展:MySQL 時區設置常用 SQL 命令

# 查看當前會話時區SELECT @@session.time_zone;# 設置當前會話時區SETtime_zone = 'Europe/Helsinki';SETtime_zone = "+00:00";# 數據庫全局時區設置SELECT @@global.time_zone;# 設置全局時區SETGLOBALtime_zone = '+8:00';SETGLOBALtime_zone = 'Europe/Helsinki';


2、占用空間

下圖是 MySQL 日期類型所占的存儲空間(官方文檔傳送門:https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html):


?


在 MySQL 5.6.4 之前,DateTime 和 TIMESTAMP 的存儲空間是固定的,分別為 8 字節和 4 字節。但是從 MySQL 5.6.4 開始,它們的存儲空間會根據毫秒精度的不同而變化,DateTime 的范圍是 5~8 字節,TIMESTAMP 的范圍是 4~7 字節。


3、表示范圍

TIMESTAMP 表示的時間范圍更小,只能到 2038 年:

  • DATETIME:'1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'

  • TIMESTAMP:'1970-01-01 00:00:01.000000' UTC 到 '2038-01-19 03:14:07.999999' UTC


4、性能

由于 TIMESTAMP 在存儲和檢索時需要進行 UTC 與當前會話時區的轉換,這個過程可能涉及到額外的計算開銷,尤其是在需要調用操作系統底層接口獲取或處理時區信息時。雖然現代數據庫和操作系統對此進行了優化,但在某些極端高并發或對延遲極其敏感的場景下,DATETIME 因其不涉及時區轉換,處理邏輯相對更簡單直接,可能會表現出微弱的性能優勢。

為了獲得可預測的行為并可能減少 TIMESTAMP 的轉換開銷,推薦的做法是在應用程序層面統一管理時區,或者在數據庫連接/會話級別顯式設置 time_zone 參數,而不是依賴服務器的默認或操作系統時區。


三、數值時間戳是更好的選擇嗎?


除了上述兩種類型,實踐中也常用整數類型(INT 或 BIGINT)來存儲所謂的“Unix 時間戳”(即從 1970 年 1 月 1 日 00:00:00 UTC 起至目標時間的總秒數,或毫秒數)。


這種存儲方式的具有 TIMESTAMP 類型的所具有一些優點,并且使用它的進行日期排序以及對比等操作的效率會更高,跨系統也很方便,畢竟只是存放的數值。缺點也很明顯,就是數據的可讀性太差了,你無法直觀的看到具體時間。


時間戳的定義如下:

時間戳的定義是從一個基準時間開始算起,這個基準時間是「1970-1-1 00:00:00 +0:00」,從這個時間開始,用整數表示,以秒計時,隨著時間的流逝這個時間整數不斷增加。這樣一來,我只需要一個數值,就可以完美地表示時間了,而且這個數值是一個絕對數值,即無論的身處地球的任何角落,這個表示時間的時間戳,都是一樣的,生成的數值都是一樣的,并且沒有時區的概念,所以在系統的中時間的傳輸中,都不需要進行額外的轉換了,只有在顯示給用戶的時候,才轉換為字符串格式的本地時間。

數據庫中實際操作:

-- 將日期時間字符串轉換為 Unix 時間戳 (秒)mysql> SELECTUNIX_TIMESTAMP('2020-01-11 09:53:32');+---------------------------------------+| UNIX_TIMESTAMP('2020-01-11 09:53:32'|+---------------------------------------+|                            1578707612 |+---------------------------------------+1 row in set (0.00 sec)-- 將 Unix 時間戳 (秒) 轉換為日期時間格式mysql> SELECT FROM_UNIXTIME(1578707612);+---------------------------+| FROM_UNIXTIME(1578707612|+---------------------------+| 2020-01-11 09:53:32       |+---------------------------+1 row in set (0.01 sec)


四、PostgreSQL 中沒有 DATETIME


由于有讀者提到 PostgreSQL(PG) 的時間類型,因此這里拓展補充一下。PG 官方文檔對時間類型的描述地址:https://www.postgresql.org/docs/current/datatype-datetime.html。


PostgreSQL 時間類型總結


可以看到,PG 沒有名為 DATETIME 的類型:

  • PG 的 TIMESTAMP WITHOUT TIME ZONE在功能上最接近 MySQL 的 DATETIME。它存儲日期和時間,但不包含任何時區信息,存儲的是字面值。

  • PG 的TIMESTAMP WITH TIME ZONE (或 TIMESTAMPTZ) 相當于 MySQL 的 TIMESTAMP。它在存儲時會將輸入值轉換為 UTC,并在檢索時根據當前會話的時區進行轉換顯示。

對于絕大多數需要記錄精確發生時間點的應用場景,TIMESTAMPTZ是 PostgreSQL 中最推薦、最健壯的選擇,因為它能最好地處理時區復雜性。


五、總結


MySQL 中時間到底怎么存儲才好?DATETIME?TIMESTAMP?還是數值時間戳?

并沒有一個銀彈,很多程序員會覺得數值型時間戳是真的好,效率又高還各種兼容,但是很多人又覺得它表現的不夠直觀。

《高性能 MySQL 》這本神書的作者就是推薦 TIMESTAMP,原因是數值表示時間不夠直觀。下面是原文:

?


每種方式都有各自的優勢,根據實際場景選擇最合適的才是王道。下面再對這三種方式做一個簡單的對比,以供大家實際開發中選擇正確的存放時間的數據類型:

類型
存儲空間
日期格式
日期范圍
是否帶時區信息
DATETIME
5~8 字節
YYYY-MM-DD hh:mm:ss[.fraction]
1000-01-01 00:00:00[.000000] ~ 9999-12-31 23:59:59[.999999]
TIMESTAMP
4~7 字節
YYYY-MM-DD hh:mm:ss[.fraction]
1970-01-01 00:00:01[.000000] ~ 2038-01-19 03:14:07[.999999]
數值型時間戳
4 字節
全數字如 1578707612
1970-01-01 00:00:01 之后的時間


擇建議小結:

  • TIMESTAMP 的核心優勢在于其內建的時區處理能力。數據庫負責 UTC 存儲和基于會話時區的自動轉換,簡化了需要處理多時區應用的開發。如果應用需要處理多時區,或者希望數據庫能自動管理時區轉換,TIMESTAMP 是自然的選擇(注意其時間范圍限制,也就是 2038 年問題)。

  • 如果應用場景不涉及時區轉換,或者希望應用程序完全控制時區邏輯,并且需要表示 2038 年之后的時間,DATETIME 是更穩妥的選擇。

  • 如果極度關注比較性能,或者需要頻繁跨系統傳遞時間數據,并且可以接受可讀性的犧牲(或總是在應用層轉換),數值時間戳是一個強大的選項。


作者丨Guide
來源丨公眾號:JavaGuide(ID:JavaGuide)


該文章在 2025/6/3 9:15:58 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved