MySQL?數(shù)據(jù)庫如何實(shí)現(xiàn)存儲(chǔ)時(shí)間
1.切記不要用字符串存儲(chǔ)日期
字符串占用的空間更大!
字符串存儲(chǔ)的日期比較效率比較低(逐個(gè)字符進(jìn)行比對(duì)),無法用日期相關(guān)的 API 進(jìn)行計(jì)算和比較。
2.Datetime 和 Timestamp 之間抉擇
Datetime 和 Timestamp 是 MySQL 提供的兩種比較相似的保存時(shí)間的數(shù)據(jù)類型。
他們兩者究竟該如何選擇呢?
通常我們都會(huì)首選 Timestamp
2.1 DateTime 類型沒有時(shí)區(qū)信息的
DateTime 類型是沒有時(shí)區(qū)信息的(時(shí)區(qū)無關(guān))
當(dāng)你的時(shí)區(qū)更換之后,比如你的服務(wù)器更換地址或者更換客戶端連接時(shí)區(qū)設(shè)置的話,就會(huì)導(dǎo)致你從數(shù)據(jù)庫中讀出的時(shí)間錯(cuò)誤。
Timestamp 和時(shí)區(qū)有關(guān)。
Timestamp 類型字段的值會(huì)隨著服務(wù)器時(shí)區(qū)的變化而變化,自動(dòng)換算成相應(yīng)的時(shí)間,說簡單點(diǎn)就是在不同時(shí)區(qū),查詢到同一個(gè)條記錄此字段的值會(huì)不一樣。
下面實(shí)際演示一下!
建表 SQL 語句:
CREATE TABLE `time_zone_test` ( ? `id` bigint(20) NOT NULL AUTO_INCREMENT, ? `date_time` datetime DEFAULT NULL, ? `time_stamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, ? PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入數(shù)據(jù):
INSERT INTO time_zone_test(date_time,time_stamp) VALUES(NOW(),NOW());
查看數(shù)據(jù):
select dsqlate_time,time_stamp from time_zone_test;
結(jié)果:
+---------------------+---------------------+
| date_time | time_stamp |
+---------------------+---------------------+
| 2020-01-11 09:53:32 | 2020-01-11 09:53:32 |
+---------------------+---------------------+
修改當(dāng)前會(huì)話的時(shí)區(qū):
set time_zone='+8:00';
再次查看數(shù)據(jù):
+---------------------+---------------------+
| date_time | time_stamp |
+---------------------+---------------------+
| 2020-01-11 09:53:32 | 2020-01-11 17:53:32 |
+---------------------+---------------------+
擴(kuò)展: 一些關(guān)于 MySQL 時(shí)區(qū)設(shè)置的一個(gè)常用 sql 命令
1. 查看當(dāng)前會(huì)話時(shí)區(qū)
?? ?SELECT @@session.time_zone;
2. 設(shè)置當(dāng)前會(huì)話時(shí)區(qū)
?? ?SET time_zone = 'Europe/Helsinki'; ?? ?SET time_zone = "+00:00";
3. 數(shù)據(jù)庫全局時(shí)區(qū)設(shè)置
?? ?SELECT @@global.time_zone;
4. 設(shè)置全局時(shí)區(qū)
? ? SET GLOBAL time_zone = '+8:00'; ?? ?SET GLOBAL time_zone = 'Europe/Helsinki';
2.2 DateTime 類型耗費(fèi)空間更大
Timestamp 只需要使用 4 個(gè)字節(jié)的存儲(chǔ)空間,但是 DateTime 需要耗費(fèi) 8 個(gè)字節(jié)的存儲(chǔ)空間。但是,這樣同樣造成了一個(gè)問題,Timestamp 表示的時(shí)間范圍更小。
DateTime
:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59Timestamp
: 1970-01-01 00:00:01 ~ 2037-12-31 23:59:59
Timestamp 在不同版本的 MySQL 中有細(xì)微差別。
3.再看 MySQL 日期類型存儲(chǔ)空間
下圖是 MySQL 5.6 版本中日期類型所占的存儲(chǔ)空間:
可以看出 5.6.4 之后的 MySQL 多出了一個(gè)需要 0 ~ 3 字節(jié)的小數(shù)位。Datatime 和 Timestamp 會(huì)有幾種不同的存儲(chǔ)空間占用。
為了方便,本文我們還是默認(rèn) Timestamp 只需要使用 4 個(gè)字節(jié)的存儲(chǔ)空間,但是 DateTime 需要耗費(fèi) 8 個(gè)字節(jié)的存儲(chǔ)空間。
4.數(shù)值型時(shí)間戳是更好的選擇嗎?
很多時(shí)候,我們也會(huì)使用 int 或者 bigint 類型的數(shù)值也就是時(shí)間戳來表示時(shí)間。
這種存儲(chǔ)方式的具有 Timestamp 類型的所具有一些優(yōu)點(diǎn),并且使用它的進(jìn)行日期排序以及對(duì)比等操作的效率會(huì)更高,跨系統(tǒng)也很方便,畢竟只是存放的數(shù)值。缺點(diǎn)也很明顯,就是數(shù)據(jù)的可讀性太差了,你無法直觀的看到具體時(shí)間。
時(shí)間戳的定義如下:
時(shí)間戳的定義是從一個(gè)基準(zhǔn)時(shí)間開始算起,這個(gè)基準(zhǔn)時(shí)間是「1970-1-1 00:00:00 +0:00」,從這個(gè)時(shí)間開始,用整數(shù)表示,以秒計(jì)時(shí),隨著時(shí)間的流逝這個(gè)時(shí)間整數(shù)不斷增加。
這樣一來,我只需要一個(gè)數(shù)值,就可以完美地表示時(shí)間了,而且這個(gè)數(shù)值是一個(gè)絕對(duì)數(shù)值,即無論的身處地球的任何角落,這個(gè)表示時(shí)間的時(shí)間戳,都是一樣的,生成的數(shù)值都是一樣的,并且沒有時(shí)區(qū)的概念,所以在系統(tǒng)的中時(shí)間的傳輸中,都不需要進(jìn)行額外的轉(zhuǎn)換了,只有在顯示給用戶的時(shí)候,才轉(zhuǎn)換為字符串格式的本地時(shí)間。
數(shù)據(jù)庫中實(shí)際操作:
mysql> select UNIX_TIMESTAMP('2020-01-11 09:53:32'); +---------------------------------------+ | UNIX_TIMESTAMP('2020-01-11 09:53:32') | +---------------------------------------+ | 1578707612 | +---------------------------------------+ 1 row in set (0.00 sec) mysql> select FROM_UNIXTIME(1578707612); +---------------------------+ | FROM_UNIXTIME(1578707612) | +---------------------------+ | 2020-01-11 09:53:32 | +---------------------------+ 1 row in set (0.01 sec)
5.總結(jié)
推薦 Timestamp,原因是數(shù)值表示時(shí)間不夠直觀
每種方式都有各自的優(yōu)勢,根據(jù)實(shí)際場景才是王道。下面再對(duì)這三種方式做一個(gè)簡單的對(duì)比,以供大家實(shí)際開發(fā)中選擇正確的存放時(shí)間的數(shù)據(jù)類型:
6.設(shè)置mysql date類型字段默認(rèn)值支持0000格式
[mysqld] sql-mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
遠(yuǎn)程連接mysql數(shù)據(jù)庫注意事項(xiàng)記錄(遠(yuǎn)程連接慢skip-name-resolve)
有時(shí)候我們需要遠(yuǎn)程連接mysql數(shù)據(jù)庫,就需要注意下面的問題,方便大家解決,腳本之家小編特為大家準(zhǔn)備了一些資料2012-07-07MySQL百萬級(jí)數(shù)據(jù)大分頁查詢優(yōu)化的實(shí)現(xiàn)
在數(shù)據(jù)庫開發(fā)過程中我們經(jīng)常會(huì)使用分頁,但是如果是百萬級(jí)數(shù)據(jù)呢,本文就詳細(xì)的介紹一下MySQL百萬級(jí)數(shù)據(jù)大分頁查詢優(yōu)化的實(shí)現(xiàn),感興趣的可以了解一下2022-01-01MySQL學(xué)習(xí)筆記之?dāng)?shù)據(jù)定義表約束,分頁方法總結(jié)
這篇文章主要介紹了MySQL學(xué)習(xí)筆記之?dāng)?shù)據(jù)定義表約束,分頁方法,結(jié)合實(shí)例形式總結(jié)分析了數(shù)據(jù)定義、主鍵、外鍵、自增長、約束等概念與用法,并給出了關(guān)于分頁的實(shí)例與相關(guān)操作技巧,需要的朋友可以參考下2016-09-09MySQL關(guān)于ERROR 1290 (HY000)報(bào)錯(cuò)解決方法
在本篇文章里小編給大家整理的是關(guān)于MySQL關(guān)于ERROR 1290 (HY000)報(bào)錯(cuò)的解決方法,有興趣的朋友們可以參考下。2019-09-09mysql 正則表達(dá)式查詢含有非數(shù)字和字符的記錄
這篇文章主要介紹了mysql 正則表達(dá)式查詢含有非數(shù)字和字符的記錄的相關(guān)資料,需要的朋友可以參考下2016-12-12SQL中where語句的用法及實(shí)例代碼(條件查詢)
WHERE如需有條件地從表中選取數(shù)據(jù),可將WHERE 子句添加到SELECT語句,下面這篇文章主要給大家介紹了關(guān)于SQL中where語句的用法及實(shí)例(條件查詢)的相關(guān)資料,需要的朋友可以參考下2022-10-10