Tôi nên sử dụng kiểu dữ liệu datetime hay dấu thời gian trong MySQL?


2686

Bạn có khuyên bạn nên sử dụng datetime hoặc trường dấu thời gian và tại sao (sử dụng MySQL)?

Tôi đang làm việc với PHP ở phía máy chủ.


1
điều này có một số thông tin liên quan codeproject.com/Tips/1215635/MySQL-DATETIME-vs-TIMESTAMP
Waqleh

Nếu bạn muốn ứng dụng của bạn bị hỏng vào tháng 2 năm 2038, hãy sử dụng dấu thời gian. Kiểm tra phạm vi ngày.
Wilson Hauck

Câu trả lời:


1830

Dấu thời gian trong MySQL thường được sử dụng để theo dõi các thay đổi đối với bản ghi và thường được cập nhật mỗi khi bản ghi được thay đổi. Nếu bạn muốn lưu trữ một giá trị cụ thể, bạn nên sử dụng trường datetime.

Nếu bạn có nghĩa là bạn muốn quyết định giữa việc sử dụng dấu thời gian UNIX hoặc trường thời gian MySQL gốc, hãy đi với định dạng gốc. Bạn có thể thực hiện các phép tính trong MySQL theo cách đó ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")và thật đơn giản để thay đổi định dạng của giá trị thành dấu thời gian UNIX ("SELECT UNIX_TIMESTAMP(my_datetime)")khi bạn truy vấn bản ghi nếu bạn muốn thao tác với nó bằng PHP.


981
Một sự khác biệt quan trọng là DATETIMEđại diện cho một ngày (như được tìm thấy trong lịch) và thời gian (như có thể được quan sát trên đồng hồ treo tường), trong khi TIMESTAMPđại diện cho một thời điểm được xác định rõ. Điều này có thể rất quan trọng nếu ứng dụng của bạn xử lý múi giờ. Đã bao lâu rồi '2010-09-01 16:31:00'? Nó phụ thuộc vào múi giờ bạn đang ở. Đối với tôi, đó chỉ là một vài giây trước, đối với bạn nó có thể đại diện cho một thời gian trong tương lai. Nếu tôi nói 1283351460 giây kể từ '1970-01-01 00:00:00 UTC', bạn sẽ biết chính xác thời điểm tôi nói về thời điểm nào. (Xem câu trả lời xuất sắc của Nir bên dưới). [Nhược điểm: phạm vi hợp lệ].
MattBianco

121
Một điểm khác biệt nữa: các truy vấn với datetime "gốc" sẽ không được lưu trong bộ nhớ cache, nhưng các truy vấn có dấu thời gian - sẽ là.
OZ_

39
"Dấu thời gian trong MySQL thường được sử dụng để theo dõi các thay đổi đối với hồ sơ" Đừng nghĩ đó là một câu trả lời hay. Dấu thời gian mạnh hơn và phức tạp hơn nhiều so với MattBianco và Nir sayd. Mặc dù, phần thứ hai của câu trả lời là rất tốt. Đó là sự thật những gì Blivet đã nói, và là một lời khuyên tốt.
santiagobasulto

10
Ngoài ra, 1 lưu ý quan trọng, DATETIME và TIMESTAMP có thể sử dụng CURRENT_TIMESTAMP, NOW () một cách tôn trọng như giá trị mặc định của nó, nhưng DATE chẳng hạn, vì nó sử dụng '0000-00-00' theo mặc định, vì vậy để giải quyết vấn đề đó U nên viết Trình kích hoạt của riêng bạn vào bảng đó, để chèn ngày hiện tại (không có thời gian) vào trường / col với loại DATE mysql.
Arthur Kushman

14
@DavidHarkness: Tài liệu nói "Để xác định tính chất tự động, sử dụng DEFAULT CURRENT_TIMESTAMP và ON UPDATE CURRENT_TIMESTAMP khoản" dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
Plap

917

Trong MySQL 5 trở lên, các giá trị TIMESTAMP được chuyển đổi từ múi giờ hiện tại sang UTC để lưu trữ và được chuyển đổi trở lại từ UTC sang múi giờ hiện tại để truy xuất. (Điều này chỉ xảy ra đối với loại dữ liệu TIMESTAMP và không xảy ra đối với các loại khác như DATETIME.)

Theo mặc định, múi giờ hiện tại cho mỗi kết nối là thời gian của máy chủ. Múi giờ có thể được đặt trên cơ sở mỗi kết nối, như được mô tả trong Hỗ trợ múi giờ của máy chủ MySQL .


11
bản trình bày OReilly này rất tốt cho chủ đề này (PDF xin lỗi) cdn.oreillystatic.com/en/assets/1/event/36/iêu
gcb

13
Nó cũng nói về bản chất của sự kiện: - Một hội nghị video (TIMESTAMP). Tất cả các tiếp viên sẽ thấy một tham chiếu đến một thời gian tuyệt đối được điều chỉnh theo múi giờ của nó. - Một thời gian nhiệm vụ địa phương (DATETIME), tôi nên thực hiện nhiệm vụ này vào 2014/03/31 9:00 AM không có vấn đề gì nếu ngày đó tôi đang làm việc ở New York hoặc Paris. Tôi sẽ bắt đầu làm việc lúc 8:00 sáng theo giờ địa phương, tôi sẽ đến vào ngày hôm đó.
yucer 17/12/13

1
Vì vậy, nếu tôi THAY ĐỔI múi giờ của máy chủ, thì giá trị của TIMESTAMP sẽ giữ nguyên hoặc nó cũng sẽ thay đổi ??
Andrew

3
@Andrew kể từ khi nó là UTC, nó sẽ ở lại UTC. Tuy nhiên, chuyển đổi ngược sẽ thay đổi thành múi giờ máy chủ "mới".
nembleton

@yucer - Tôi không khuyên bạn nên nghĩ về nó theo cách đó. Việc sử dụng nhất quán trong nền kinh tế toàn cầu là chuyển đổi tất cả các thời gian dữ liệu sang UTC để lưu trữ. Theo quy ước, coi Datetime là một trường UTC. Điều này không đặt gánh nặng lên tất cả các nhiệm vụ nhập dữ liệu thời gian để thực hiện chuyển đổi sang UTC, nhưng nó là một thiết kế sạch hơn về lâu dài. Tất nhiên, trình bày thông tin cho người dùng dựa trên các cài đặt hiện tại của họ. Nếu người dùng muốn nhập "09:00 tại Paris", thì hãy để họ đặt giờ Paris, sau đó nhập 09:00. Sau đó, bất cứ ai ở New York cũng có thể dễ dàng tìm thấy thời gian họ cần thức dậy vào thời gian của họ, để giao tiếp từ xa.
ToolmakerSteve

524

Tôi luôn sử dụng các trường DATETIME cho bất kỳ thứ gì ngoài siêu dữ liệu hàng (ngày được tạo hoặc sửa đổi).

Như đã đề cập trong tài liệu MySQL:

Loại DATETIME được sử dụng khi bạn cần các giá trị chứa cả thông tin ngày và thời gian. MySQL truy xuất và hiển thị các giá trị DATETIME ở định dạng 'YYYY-MM-DD HH: MM: SS'. Phạm vi được hỗ trợ là '1000-01-01 00:00:00' đến '9999-12-31 23:59:59'.

...

Kiểu dữ liệu TIMESTAMP có phạm vi từ '1970-01-01 00:00:01' UTC đến '2038-01-09 03:14:07' UTC. Nó có các thuộc tính khác nhau, tùy thuộc vào phiên bản MySQL và chế độ SQL mà máy chủ đang chạy.

Bạn hoàn toàn có khả năng đạt giới hạn thấp hơn trên TIMESTAMPs trong sử dụng chung - ví dụ: lưu trữ ngày sinh.


195
bạn cũng có thể dễ dàng đạt đến giới hạn trên nếu bạn đang ở trong ngân hàng hoặc bất động sản ... Thế chấp 30 năm vượt quá 2038 bây giờ
Kip

16
Tất nhiên, sử dụng dấu thời gian Unix 64 bit. Ví dụ, trong Java, new Date().getTime()đã cung cấp cho bạn giá trị 64 bit.
osa

5
+1 cho DATETIME: Trong luồng dữ liệu của chúng tôi, từ Máy chủ SQL của Cửa hàng vật lý để mua và hóa đơn, được chuyển đến Máy chủ MySQL cho Cửa hàng ảo trên trang web, DATETIME tốt hơn cho Ngày sửa đổi vì loại dữ liệu này cũng tồn tại trong Giao dịch -Có thể. Nhưng TIMESTAMP có nghĩa là một thứ khác trong Transact-SQL, nó là Nhị phân như ROWVERSION, mặc dù MySQL TIMESTAMP tương tự DateTime. Vì vậy, chúng tôi tránh việc sử dụng TIMESTAMP cho khả năng tương thích của hai DB.
jacouh

10
Không ý kiến. Đó là một vấn đề lớn hơn nhiều so với chỉ MySQL và không có sửa chữa đơn giản: en.wikipedia.org/wiki/Year_2038_problem Tôi không tin MySQL chỉ có thể tuyên bố timestamps hiện nay có 64-bit và giả định tất cả mọi thứ sẽ ổn thôi. Họ không kiểm soát phần cứng.
scronide

5
Ngày sinh có thể là một ĐỔI MỚI nếu bạn biết thời gian sinh, như tôi làm cho tôi.
Kris Craig

322

Các ví dụ dưới đây cho thấy TIMESTAMPloại ngày thay đổi các giá trị sau khi thay đổi vị time-zone to 'america/new_york'trí DATETIMEkhông thay đổi.

mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name    | Value               |
+------------------+---------------------+
| system_time_zone | India Standard Time |
| time_zone        | Asia/Calcutta       |
+------------------+---------------------+

mysql> create table datedemo(
    -> mydatetime datetime,
    -> mytimestamp timestamp
    -> );

mysql> insert into datedemo values ((now()),(now()));

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 14:11:09 |
+---------------------+---------------------+

mysql> set time_zone="america/new_york";

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+

Tôi đã chuyển đổi câu trả lời của mình thành bài viết để nhiều người có thể tìm thấy loại dữ liệu hữu ích này : MySQL: Datetime Versus Timestamp .


55
Chà, thực ra DATETIMEthời gian hiệu quả đã thay đổi theo sự thay đổi múi giờ, TIMESTAMPkhông thay đổi nhưng đại diện của con người thì có.
flindeberg

3
Có vẻ như lệnh này không hoạt động trong MySQL 5.6 set time_zone="america/new_york";
Manjunath Reddy

Đây là câu trả lời cho vấn đề time_zone đã đặt. stackoverflow.com/questions/3451847/mysql-timezone-change
Manjunath Reddy

2
Đồng ý với @flindeberg. Dấu thời gian biểu thị thời gian chính xác, không phải thời gian, sau khi thay đổi múi giờ
Nitin Bansal

193

Sự khác biệt chính là DATETIME không đổi trong khi TIMESTAMP bị ảnh hưởng bởi time_zonecài đặt.

Vì vậy, nó chỉ quan trọng khi bạn có - hoặc có thể trong tương lai có - các cụm được đồng bộ hóa theo các múi giờ.

Nói một cách đơn giản hơn: Nếu tôi có cơ sở dữ liệu ở Úc và lấy một cơ sở dữ liệu đó để đồng bộ hóa / điền vào cơ sở dữ liệu ở Mỹ, thì TIMESTAMP sẽ cập nhật để phản ánh thời gian thực của sự kiện trong múi giờ mới, trong khi đó, DATETIME sẽ vẫn phản ánh thời gian của sự kiện trong múi giờ au .

Một ví dụ tuyệt vời về việc sử dụng DATETIME trong đó TIMESTAMP nên được sử dụng là ở Facebook, nơi máy chủ của họ không bao giờ chắc chắn những gì thời gian xảy ra trên các múi giờ. Khi tôi đang có một cuộc trò chuyện trong đó thời gian nói rằng tôi đang trả lời tin nhắn trước khi tin nhắn thực sự được gửi. (Tất nhiên, điều này cũng có thể đã được gây ra bởi bản dịch múi giờ xấu trong phần mềm nhắn tin nếu thời gian được đăng chứ không phải đồng bộ hóa.)


83
Tôi không nghĩ rằng đây là một cách suy nghĩ tốt. Tôi chỉ lưu trữ và xử lý tất cả các ngày trong UTC và đảm bảo rằng giao diện người dùng hiển thị nó theo múi giờ nhất định. Cách tiếp cận này là đơn giản và có thể dự đoán.
Kos

8
@Kos: không lưu trữ và xử lý tất cả các ngày trong UTC chính xác những gì TIMESTAMP đang làm trong nội bộ? (Sau đó chuyển đổi nó để hiển thị múi giờ địa phương của bạn?)
carbocation

10
múi giờ địa phương của tôi ? Làm thế nào DB của bạn biết múi giờ của tôi? ;-) Thông thường có khá nhiều xử lý giữa cơ sở dữ liệu và giao diện người dùng. Tôi làm nội địa hóa chỉ sau khi xử lý toàn bộ.
Kos

3
@Koz: cơ sở dữ liệu của tôi không biết múi giờ cơ sở dữ liệu của bạn :! Nhưng nó biết dấu thời gian. Cơ sở dữ liệu của bạn biết cài đặt múi giờ của chính nó và áp dụng điều đó khi diễn giải / biểu diễn dấu thời gian. 1:01 sáng ngày 11 tháng 12 năm 2013 tại Bắc Kinh Trung Quốc không phải là cùng thời điểm với 1:01 sáng ngày 11 tháng 12 năm 2013 tại Sydney Úc. Google: 'múi giờ' và 'kinh tuyến gốc'.
ekerner

2
MySQL chuyển đổi các giá trị TIMESTAMP từ múi giờ hiện tại sang UTC để lưu trữ và quay lại từ UTC thành múi giờ hiện tại để truy xuất. (Điều này không xảy ra đối với các loại khác, chẳng hạn như DATETIME.) Dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo

125

Tôi đưa ra quyết định này trên cơ sở ngữ nghĩa.

Tôi sử dụng dấu thời gian khi tôi cần ghi lại thời điểm cố định (nhiều hơn hoặc ít hơn). Ví dụ: khi một bản ghi được chèn vào cơ sở dữ liệu hoặc khi một số hành động của người dùng diễn ra.

Tôi sử dụng trường datetime khi ngày / giờ có thể được đặt và thay đổi tùy ý. Ví dụ khi người dùng có thể lưu các cuộc hẹn thay đổi sau này.


dấu thời gian - thời gian cố định theo thời gian, thời gian theo thời gian quốc tế phối hợp - liên quan đến quan điểm, đến tham chiếu thời gian (ej múi giờ địa phương), có thể được .. Thời gian địa phương phối hợp?
yucer 17/12/13

110

Tôi khuyên bạn không nên sử dụng trường DATETIME hoặc TIMESTAMP. Nếu bạn muốn đại diện cho một ngày cụ thể (như sinh nhật), thì hãy sử dụng loại DATE, nhưng nếu bạn cụ thể hơn thế, có lẽ bạn thích ghi lại một khoảnh khắc thực tế trái ngược với một đơn vị thời gian (ngày, tuần, tháng, năm). Thay vì sử dụng DATETIME hoặc TIMESTAMP, hãy sử dụng BIGINT và chỉ cần lưu trữ số mili giây kể từ epoch (System.cienTimeMillis () nếu bạn đang sử dụng Java). Điều này có một số lợi thế:

  1. Bạn tránh bị khóa nhà cung cấp. Khá nhiều cơ sở dữ liệu hỗ trợ các số nguyên theo cách tương đối giống nhau. Giả sử bạn muốn chuyển sang cơ sở dữ liệu khác. Bạn có muốn lo lắng về sự khác biệt giữa các giá trị DATETIME của MySQL và cách Oracle định nghĩa chúng không? Ngay cả trong số các phiên bản khác nhau của MySQL, TIMESTAMPS có mức độ chính xác khác nhau. Chỉ mới gần đây, MySQL hỗ trợ mili giây trong dấu thời gian.
  2. Không có vấn đề múi giờ. Có một số ý kiến ​​sâu sắc ở đây về những gì xảy ra với các múi giờ với các loại dữ liệu khác nhau. Nhưng đây có phải là kiến ​​thức phổ biến, và tất cả đồng nghiệp của bạn sẽ dành thời gian để tìm hiểu nó? Mặt khác, thật khó để thay đổi BigINT thành java.util.Date. Sử dụng BIGINT gây ra rất nhiều vấn đề với các múi giờ rơi bên đường.
  3. Không phải lo lắng về phạm vi hoặc độ chính xác. Bạn không phải lo lắng về những gì bị cắt ngắn bởi các phạm vi ngày trong tương lai (TIMESTAMP chỉ đến năm 2038).
  4. Tích hợp công cụ của bên thứ ba. Bằng cách sử dụng một số nguyên, việc các công cụ của bên thứ 3 (ví dụ EclipseLink) giao tiếp với cơ sở dữ liệu là chuyện nhỏ. Không phải mọi công cụ của bên thứ ba sẽ có cùng cách hiểu về "datetime" như MySQL. Muốn thử và tìm hiểu trong Hibernate xem bạn nên sử dụng đối tượng java.sql.TimeStamp hoặc java.util.Date nếu bạn đang sử dụng các loại dữ liệu tùy chỉnh này? Sử dụng các loại dữ liệu cơ sở của bạn giúp việc sử dụng với các công cụ của bên thứ 3 trở nên tầm thường.

Vấn đề này liên quan chặt chẽ đến việc bạn nên lưu trữ giá trị tiền như thế nào (ví dụ $ 1.99) trong cơ sở dữ liệu. Bạn có nên sử dụng loại Tiền thập phân hoặc loại tiền của cơ sở dữ liệu hoặc tệ nhất trong tất cả số tiền gấp đôi? Cả 3 tùy chọn này đều rất tệ, vì nhiều lý do tương tự được liệt kê ở trên. Giải pháp là lưu trữ giá trị của tiền bằng xu bằng BIGINT, sau đó chuyển đổi xu sang đô la khi bạn hiển thị giá trị cho người dùng. Công việc của cơ sở dữ liệu là lưu trữ dữ liệu và KHÔNG truyền dữ liệu đó. Tất cả các kiểu dữ liệu ưa thích mà bạn thấy trong cơ sở dữ liệu (đặc biệt là Oracle) thêm rất ít và bắt đầu cho bạn đến với nhà cung cấp khóa.


12
Tôi thích giải pháp này. TIMESTAMP hết hạn vào năm 2038 là một vấn đề lớn. Điều đó thực sự không quá xa!
Charlie Dalsass

4
@CharlieDalsass Bạn có nghĩ rằng phần mềm hiện tại sẽ ở đó vào lúc đó :-P
Habeeb Perwad

13
Thật khó để truy vấn dữ liệu theo ngày nếu nó được lưu trữ dưới dạng một phần nghìn giây
Ali Saeed

4
Đây thực sự là giải pháp tốt nhất nếu bạn quan tâm đến tính di động và xử lý người dùng theo nhiều múi giờ hoặc cơ sở dữ liệu ở múi giờ khác với người dùng. TIMESTAMP có thể là con đường để đi nếu nó không thiết kế sai sót. Quá tệ là các giải pháp bị hỏng đã nhận được nhiều phiếu hơn vì chúng đã được đăng sớm (năm!).
Tiếng Đức

4
Giải pháp tuyệt vời! Và bạn hoàn toàn đúng khi bị "nhốt". Khi bạn có thói quen để người khác "làm việc cho bạn", thì bạn bắt đầu mất các bit và phần khiến BẠN trở thành lập trình viên.
fmc

98

TIMESTAMP là 4 byte Vs 8 byte cho DATETIME.

http://dev.mysql.com/doc/refman/5.0/en/st Storage-request.html

Nhưng giống như scronide nói rằng nó có giới hạn thấp hơn của năm 1970. Thật tuyệt vời cho bất cứ điều gì có thể xảy ra trong tương lai;)


185
Tương lai kết thúc vào lúc 2038-01-19 03:14:07 UTC.
MattBianco

5
Thật là ngu xuẩn. Tôi nghĩ loại TIMESTAMP sẽ "sẵn sàng trong tương lai" vì nó tương đối mới. Bạn không thể bận tâm chuyển đổi datetime sang UTC và quay lại mỗi lần khi bạn làm việc với các múi giờ khác nhau. Họ nên làm cho TIMESTAMP lớn hơn .. lớn hơn ít nhất 1 byte. nó sẽ thêm 68 * 255 = 17340 năm nữa ... mặc dù nó sẽ không được căn chỉnh 32 bit.
NickSoft

10
Bạn có biết tại sao TIMESTAMP kết thúc vào năm 2038 không? Bởi vì đó là một số nguyên và số nguyên có giới hạn là 2147483647. Tôi nghĩ đây là lý do. Có thể nếu họ thay đổi loại của nó thành varchar và thay đổi cách thao tác với nó, nó sẽ "sẵn sàng trong tương lai".
vinsa

6
@vinsa, tôi không nghĩ rằng nó sẽ sẵn sàng trong tương lai. Vẫn nhớ lỗi Y2K? 2038 đang đến.
Pacerier

2
Đến năm 2038, MySQL (nếu vẫn còn tồn tại) sẽ chỉ cập nhật trường TIMESTAMP để sử dụng hơn 4 byte và cho phép phạm vi rộng hơn
the_nuts

95
  1. TIMESTAMP là bốn byte so với tám byte cho DATETIME.

  2. Dấu thời gian cũng nhẹ hơn trên cơ sở dữ liệu và được lập chỉ mục nhanh hơn.

  3. Loại DATETIME được sử dụng khi bạn cần các giá trị chứa cả thông tin ngày và thời gian. MySQL truy xuất và hiển thị các giá trị DATETIME ở định dạng 'YYYY-MM-DD HH: MM: SS'. Phạm vi được hỗ trợ là '1000-01-01 00:00:00 đến' 9999-12-31 23:59:59.

Kiểu dữ liệu TIMESTAMP có phạm vi '1970-01-01 00:00:01 UTC đến' 2038-01-09 03:14:07 UTC. Nó có các thuộc tính khác nhau, tùy thuộc vào phiên bản MySQL và chế độ SQL mà máy chủ đang chạy.

  1. DATETIME không đổi trong khi TIMESTAMP được thực hiện bằng cài đặt time_zone.

6
Bạn cần làm rõ # 4: Dấu thời gian được lưu trữ là không đổi và không liên quan (hoàn toàn không liên quan) đến múi giờ, trong khi đầu ra được hiển thị khi truy xuất bị ảnh hưởng bởi múi giờ của phiên yêu cầu. DATETIME luôn liên quan đến múi giờ mà nó được ghi lại và phải luôn được xem xét trong bối cảnh đó, một trách nhiệm hiện thuộc về ứng dụng.
Christopher McGowan

1
Câu trả lời chính xác. Để thêm vào câu trả lời này, nếu chúng tôi cố gắng lưu trữ các giá trị vượt quá '2038-01-09 03:14:07', chúng tôi sẽ gặp lỗi hoặc được lưu trữ dưới dạng '0000-00-00 00:00:00'. Tôi đã nhận được lỗi này cho cơ sở dữ liệu của mình vì nó có các giá trị chuyển đổi thời gian (cho mục đích mã hóa).
KarthikS

Ngoài ra, có một vấn đề với DATETIME với giá trị DEFAULT trên các phiên bản mysql dưới 5.5. dba.stackexchange.com/questions/132951/ từ
Velaro

47

Phụ thuộc vào ứng dụng, thực sự.

Cân nhắc đặt dấu thời gian của người dùng đến máy chủ ở New York, để lấy hẹn ở Sanghai. Bây giờ khi người dùng kết nối ở Sanghai, anh ta truy cập cùng dấu thời gian cuộc hẹn từ một máy chủ được nhân đôi ở Tokyo. Anh ta sẽ thấy cuộc hẹn ở Tokyo, bù vào thời gian ban đầu ở New York.

Vì vậy, đối với các giá trị thể hiện thời gian của người dùng như cuộc hẹn hoặc lịch biểu, datetime sẽ tốt hơn. Nó cho phép người dùng kiểm soát ngày giờ chính xác mong muốn, bất kể cài đặt máy chủ. Thời gian đã đặt là thời gian đã đặt, không bị ảnh hưởng bởi múi giờ của máy chủ, múi giờ của người dùng hoặc bởi những thay đổi trong cách tính thời gian tiết kiệm ánh sáng ban ngày (vâng, nó thay đổi).

Mặt khác, đối với các giá trị thể hiện thời gian hệ thống như giao dịch thanh toán, sửa đổi bảng hoặc ghi nhật ký, luôn sử dụng dấu thời gian. Hệ thống sẽ không bị ảnh hưởng bằng cách di chuyển máy chủ sang múi giờ khác hoặc khi so sánh giữa các máy chủ theo các múi giờ khác nhau.

Dấu thời gian cũng nhẹ hơn trên cơ sở dữ liệu và được lập chỉ mục nhanh hơn.


Ứng dụng của bạn không nên dựa vào múi giờ của máy chủ. Một ứng dụng LUÔN LUÔN chọn múi giờ trong phiên kết nối cơ sở dữ liệu mà nó sử dụng trước khi đưa ra bất kỳ truy vấn nào. Nếu một kết nối được chia sẻ giữa nhiều người dùng (ví dụ: webapp), hãy sử dụng UTC và thực hiện chuyển đổi múi giờ ở phía kết xuất.
heo

42

2016 + : những gì tôi khuyên là đặt múi giờ Mysql của bạn thành UTC và sử dụng DATETIME:

Bất kỳ khung giao diện người dùng gần đây (Angular 1/2, Reac, Vue, ...) đều có thể dễ dàng và tự động chuyển đổi thời gian UTC của bạn sang giờ địa phương.

Ngoài ra:

(Trừ khi bạn có khả năng thay đổi múi giờ của máy chủ của bạn)


Ví dụ với AngularJs

// back-end: format for angular within the sql query
SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")...

// font-end Output the localised time
{{item.my_datetime | date :'medium' }}

Tất cả định dạng thời gian được bản địa hóa có sẵn tại đây: https://docs.angularjs.org/api/ng/filter/date


8
Dữ liệu của bạn không nên được đính kèm với cài đặt múi giờ của máy chủ của bạn. Có lẽ, nó hoạt động cho bạn nếu bạn có một hộp MySql dưới bàn của bạn
Jin

@Jin UTC có nghĩa là không có múi giờ như TIMESTAMP. Nếu tất cả các máy chủ của bạn ở trong UTC thì không có vấn đề gì. Có thể nó không hoạt động cho bạn nếu bạn có cấu hình 2000.
Sebastien Horin

TIMESTAMP có thể được nâng cấp lên giá trị 64 bit trong tương lai. Sau đó, không có vấn đề nữa.
hai lần vào

Tải toàn bộ thư viện của bên thứ ba để nắm bắt những thứ như thế này cũng không thể tuyệt vời cho hiệu suất, phải không? Cho rằng đó là phía máy khách và không ảnh hưởng đến cơ sở dữ liệu của bạn ... Tuy nhiên, bất cứ điều gì bạn làm đều phải yêu cầu kiểm tra máy chủ. Vì vậy, nghĩ về bức tranh hoàn chỉnh , nó có thực sự giúp ích cho vấn đề tốc độ không? - Tôi cảm thấy những điểm chuẩn đó hơi lạ. Sử dụng một chuỗi trong một truy vấn để so sánh các trường dấu thời gian cũng cảm thấy khá kỳ lạ. Điều đó cũng phải làm hại hiệu suất, phải không?
NoobishPro

1
Không dựa vào ứng dụng của bạn vào time_zone của máy chủ. Thay vào đó, xác định time_zone để sử dụng trên mỗi kết nối cơ sở dữ liệu: SET time_zone = '+0:00';cho UTC.
heo

37

Một timestamplĩnh vực là một trường hợp đặc biệt của datetimelĩnh vực này. Bạn có thể tạo timestampcác cột để có các thuộc tính đặc biệt; nó có thể được thiết lập để tự cập nhật khi tạo và / hoặc cập nhật.

Trong thuật ngữ cơ sở dữ liệu "lớn hơn", timestampcó một vài kích hoạt trường hợp đặc biệt trên đó.

Những gì đúng là hoàn toàn phụ thuộc vào những gì bạn muốn làm.


6
Không, sự khác biệt không chỉ là "trường hợp đặc biệt". Bởi vì các múi giờ của phiên đặt / truy vấn các giá trị được tham gia khác nhau.
heo

Tôi rất vui khi bạn đưa vào "Cái đúng là hoàn toàn phụ thuộc vào những gì bạn muốn làm." Có quá nhiều câu trả lời về trạng thái SE, mà không có sự biện minh đầy đủ, "Bạn không bao giờ phải làm X" hoặc "Bạn phải luôn luôn làm Y".
Búa búa Agi

37

TIMESTAMP luôn ở trong UTC (nghĩa là đã trôi qua vài giây kể từ 1970-01-01, trong UTC) và máy chủ MySQL của bạn tự động chuyển đổi nó thành ngày / giờ cho múi giờ kết nối. Về lâu dài, TIMESTAMP là con đường để đi bởi vì bạn biết dữ liệu tạm thời của bạn sẽ luôn ở trong UTC. Ví dụ: bạn sẽ không làm hỏng ngày của mình nếu bạn di chuyển đến một máy chủ khác hoặc nếu bạn thay đổi cài đặt múi giờ trên máy chủ của mình.

Lưu ý: múi giờ kết nối mặc định là múi giờ của máy chủ, nhưng điều này có thể (nên) thay đổi mỗi phiên (xem SET time_zone = ...).


29

So sánh giữa DATETIME, TIMESTAMP và DATE

nhập mô tả hình ảnh ở đây

Đó là [.fraction] là gì?

  • Giá trị DATETIME hoặc TIMESTAMP có thể bao gồm một phần giây phân đoạn kéo dài với độ chính xác lên đến micro giây (6 chữ số). Cụ thể, bất kỳ phần phân đoạn nào trong một giá trị được chèn vào cột DATETIME hoặc TIMESTAMP đều được lưu trữ thay vì bị loại bỏ. Tất nhiên đây là tùy chọn.

Nguồn:


24

Tôi sẽ luôn sử dụng dấu thời gian Unix khi làm việc với MySQL và PHP. Lý do chính cho việc này là phương thức ngày mặc định trong PHP sử dụng dấu thời gian làm tham số, do đó sẽ không cần phân tích cú pháp.

Để có được dấu thời gian Unix hiện tại trong PHP, chỉ cần làm time();
và trong MySQL làm SELECT UNIX_TIMESTAMP();.


6
-1 Tôi thực sự nghĩ rằng câu trả lời dưới đây là tốt hơn - sử dụng datetime cho phép bạn đẩy nhiều logic hơn để xử lý ngày vào chính MySQL, điều này có thể rất hữu ích.
Toby Hede

Không có điểm chuẩn nào cho thấy việc sắp xếp trong MySQL chậm hơn so với php?
sdkfasldf

cũng tốt, đôi khi nó tốt để sử dụng nó khi chúng ta không muốn sử dụng strtotime. (php5.3 dep)
Adam Ramadhan

bạn có thể đẩy logic vào mysql chỉ bằng cách sử dụng FROM_UNIXTIME nếu cần
inarilo

Tôi đã từng sử dụng tất cả các dấu thời gian Unix trong các ứng dụng PHP của mình và trong MySQL, tuy nhiên tôi thấy việc lưu trữ ngày và giờ trong MySQL là các loại ngày / giờ gốc thuận tiện hơn rất nhiều. Điều này đặc biệt hữu ích cho mục đích báo cáo và chỉ duyệt các bộ dữ liệu. Theo thời gian khi tôi cảm thấy thất vọng khi phải sao chép / qua các dấu thời gian Unix, tôi bắt đầu chuyển đổi. Tôi khá chắc chắn có hiệu suất và những ưu / nhược điểm khác, nhưng tùy thuộc vào sự thuận tiện trong trường hợp sử dụng của bạn có thể quan trọng hơn việc tối ưu hóa khá vi mô.
DavidScherer

24

Điều đáng chú ý trong MySQL, bạn có thể sử dụng một cái gì đó dọc theo các dòng bên dưới khi tạo các cột trong bảng của bạn:

on update CURRENT_TIMESTAMP

Điều này sẽ cập nhật thời gian tại mỗi trường hợp bạn sửa đổi một hàng và đôi khi rất hữu ích cho việc lưu trữ thông tin chỉnh sửa cuối cùng. Điều này chỉ hoạt động với dấu thời gian, không phải datetime.


17

Từ kinh nghiệm của tôi, nếu bạn muốn một trường ngày trong đó việc chèn chỉ xảy ra một lần và bạn không muốn có bất kỳ cập nhật hoặc bất kỳ hành động nào khác trên trường cụ thể đó, hãy đi với thời gian ngày .

Ví dụ: hãy xem xét một userbảng có trường NGÀY ĐĂNG KÝ . Trong userbảng đó , nếu bạn muốn biết thời gian đăng nhập cuối cùng của một người dùng cụ thể, hãy đi với một trường loại dấu thời gian để trường được cập nhật.

Nếu bạn đang tạo bảng từ phpMyAdmin , cài đặt mặc định sẽ cập nhật trường dấu thời gian khi cập nhật hàng xảy ra. Nếu dấu thời gian của bạn được gửi không cập nhật với cập nhật hàng, bạn có thể sử dụng truy vấn sau để tạo trường dấu thời gian được tự động cập nhật.

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

15

Kiểu dữ liệu dấu thời gian lưu trữ ngày và giờ, nhưng ở định dạng UTC, không phải ở định dạng múi giờ hiện tại như datetime. Và khi bạn tìm nạp dữ liệu, dấu thời gian lại chuyển đổi dữ liệu đó thành thời gian múi giờ hiện tại.

Vì vậy, giả sử bạn đang ở Hoa Kỳ và nhận dữ liệu từ máy chủ có múi giờ của Hoa Kỳ. Sau đó, bạn sẽ nhận được ngày và thời gian theo múi giờ Hoa Kỳ. Cột kiểu dữ liệu dấu thời gian luôn được cập nhật tự động khi hàng của nó được cập nhật. Vì vậy, nó có thể hữu ích để theo dõi khi một hàng cụ thể được cập nhật lần trước.

Để biết thêm chi tiết bạn có thể đọc bài viết trên blog Timestamp Vs Datetime .


Bạn có thể (nên) luôn xác định múi giờ ở cấp phiên với SET time_zone = '+0:00';(UTC tại đây) để đảm bảo những gì bạn nhận / đặt từ TIMESTAMPcác giá trị và tránh tùy thuộc vào mặc định của máy chủ time_zone có thể thay đổi.
heo

14

Tôi luôn sử dụng dấu thời gian Unix, chỉ đơn giản là để duy trì sự tỉnh táo khi xử lý nhiều thông tin về thời gian, đặc biệt là khi thực hiện các điều chỉnh cho múi giờ, thêm / bớt ngày và tương tự. Khi so sánh dấu thời gian, điều này loại trừ các yếu tố phức tạp của múi giờ và cho phép bạn tiết kiệm tài nguyên trong xử lý phía máy chủ của bạn (Cho dù đó là mã ứng dụng hoặc truy vấn cơ sở dữ liệu) trong đó bạn sử dụng số học trọng lượng nhẹ thay vì cộng / trừ thời gian ngày nặng hơn chức năng.

Một điều đáng để xem xét:

Nếu bạn đang xây dựng một ứng dụng, bạn sẽ không bao giờ biết dữ liệu của mình có thể phải được sử dụng như thế nào. Nếu bạn kết thúc việc phải so sánh một loạt các bản ghi trong bộ dữ liệu của mình, với, giả sử, một loạt các mục từ API của bên thứ ba và nói, hãy đặt chúng theo thứ tự thời gian, bạn sẽ rất vui khi có Dấu thời gian Unix cho hàng của bạn. Ngay cả khi bạn quyết định sử dụng dấu thời gian của MySQL, hãy lưu trữ dấu thời gian Unix làm bảo hiểm.


14

Trong trường hợp của tôi, tôi đặt UTC làm múi giờ cho mọi thứ: hệ thống, máy chủ cơ sở dữ liệu, v.v. mỗi khi tôi có thể. Nếu khách hàng của tôi yêu cầu múi giờ khác, thì tôi sẽ định cấu hình nó trên ứng dụng.

Tôi hầu như luôn thích dấu thời gian hơn là trường thời gian, bởi vì dấu thời gian bao gồm cả múi giờ. Vì vậy, vì thời điểm ứng dụng sẽ được truy cập từ người dùng từ các múi giờ khác nhau và bạn muốn họ thấy ngày và giờ trong múi giờ địa phương của họ, loại trường này giúp bạn dễ dàng thực hiện hơn so với khi dữ liệu được lưu trong trường datetime .

Thêm vào đó, trong trường hợp di chuyển cơ sở dữ liệu sang hệ thống với múi giờ khác, tôi sẽ cảm thấy tự tin hơn khi sử dụng dấu thời gian. Không nói các vấn đề có thể xảy ra khi tính toán sự khác biệt giữa hai thời điểm với một số lần thay đổi thời gian ở giữa và cần độ chính xác từ 1 giờ trở xuống.

Vì vậy, để tóm tắt, tôi đánh giá cao lợi thế này của dấu thời gian:

  • sẵn sàng sử dụng trên các ứng dụng quốc tế (nhiều múi giờ)
  • di chuyển dễ dàng giữa các múi giờ
  • khá dễ dàng để tính toán sự khác biệt (chỉ cần trừ cả hai dấu thời gian)
  • không phải lo lắng về ngày vào / ra một khoảng thời gian mùa hè

Vì tất cả lý do này, tôi chọn các trường UTC & dấu thời gian nơi có thể nhìn thấy. Và tôi tránh đau đầu;)


dữ liệu dấu thời gian sẽ rất vui cho người hỗ trợ ứng dụng của bạn khi ngày 20 tháng 1 năm 2038 đến. tick tock tick tock
Wilson Hauck

Loại dấu thời gian sau đó có thể được tăng thêm một chút và nhân đôi các giá trị có thể.
Roger Veganera

Kiểm tra lý thuyết của bạn để 'tăng thêm một chút' và xem liệu bạn có thể lưu trữ thành công vào ngày 1 tháng 2 năm 2038 và truy xuất nó bằng MySQL không. Hãy xem định nghĩa bảng của bạn khi hoàn thành, xin vui lòng. Bạn có thể sẽ có rất nhiều người quen trong quá khứ không vui vào tháng 2 năm 2038.
Wilson Hauck

1
@WilsonHauck Bạn sẽ phải nâng cấp phiên bản MySQL từ lâu trước năm 2038. Và TIMESTAMP mở rộng đó sẽ được xử lý bởi quá trình di chuyển. Ngoài ra, rất ít ứng dụng ngoài việc xử lý các khoản thế chấp thực sự cần quan tâm đến năm 2038 ngay bây giờ.
heo

@dolmen rất nhiều công cụ và vật liệu cấp chuyên nghiệp có bảo hành trên 20 năm. Vì vậy, một cái gì đó như warranties.expires_atkhông thể là dấu thời gian của MySQL ngày hôm nay.
alexw

13

Cảnh giác với dấu thời gian thay đổi khi bạn thực hiện câu lệnh CẬP NHẬT trên bảng. Nếu bạn có một bảng có các cột 'Tên' (varchar), 'Age' (int) và 'Date_Added' (dấu thời gian) và bạn chạy câu lệnh DML sau đây

UPDATE table
SET age = 30

sau đó, mọi giá trị trong cột 'Date_Added' của bạn sẽ được thay đổi thành dấu thời gian hiện tại.


3
dựa trên cách bạn thiết lập bảng của mình, bạn có thể kiểm soát hành vi này. nhìn vào dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Charles Faiga

5
@CharlesFaiga Hành vi mặc định là để dấu thời gian cập nhật khi có bất kỳ cột nào khác được cập nhật. Bạn phải tắt nó một cách rõ ràng nếu bạn muốn dấu thời gian giữ lại giá trị ban đầu của nó
Lloyd Banks

Đó là gì ?! bạn phải được đặt cột thời gian thànhON UPDATE CURRENT_TIMESTAMP
Kế toán م

Đây là một tính năng mà bạn phải kích hoạt rõ ràng khi tạo bảng.
heo

13

Tài liệu tham khảo lấy từ Điều này:

Sự khác biệt chính:

TIMESTAMP được sử dụng để theo dõi các thay đổi đối với các bản ghi và cập nhật mỗi khi bản ghi được thay đổi. DATETIME được sử dụng để lưu trữ giá trị cụ thể và tĩnh không bị ảnh hưởng bởi bất kỳ thay đổi nào trong hồ sơ.

TIMESTAMP cũng bị ảnh hưởng bởi các cài đặt liên quan đến TIME ZONE khác nhau. Dữ liệu không đổi.

TIMESTAMP đã chuyển đổi nội bộ múi giờ hiện tại sang UTC để lưu trữ và trong quá trình truy xuất được chuyển đổi trở lại múi giờ hiện tại. Cơ sở dữ liệu không thể làm điều này.

Phạm vi được hỗ trợ TIMESTAMP: '1970-01-01 00:00:01 UTC đến' 2038-01-19 03:14:07 range Phạm vi được hỗ trợ của UTC DATETIME: '1000-01-01 00:00:00 đến' 9999 -12-31 23:59:59


11
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       TIMESTAMP                                       |                                 DATETIME                                 |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes.                                                           | DATETIME requires 8 bytes.                                               |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format.                |
| TIMESTAMP supported range: 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC.    | DATETIME supported range: 1000-01-01 00:00:00 to 9999-12-31 23:59:59 |
| TIMESTAMP during retrieval converted back to the current time zone.                   | DATETIME can not do this.                                                |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose.    | DATETIME is used mostly for user-data.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+

10

Một điểm khác biệt giữa Dấu thời gian và Thời gian là trong Dấu thời gian, bạn không thể đặt giá trị mặc định cho NULL.


8
Rõ ràng là sai. Dưới đây là một ví dụ: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); Cột đầu tiên có thể chấp nhận giá trị NULL.
Ormoz

10

Tôi thấy tính hữu dụng vượt trội trong khả năng tự động cập nhật của TIMESTAMP dựa trên thời gian hiện tại mà không cần sử dụng các kích hoạt không cần thiết. Mặc dù đó chỉ là tôi, mặc dù TIMESTAMP là UTC như đã nói.

Nó có thể theo dõi trên các múi giờ khác nhau, vì vậy nếu bạn cần hiển thị thời gian tương đối, thì thời gian UTC là những gì bạn muốn.


9

Sự khác biệt chính là

nhìn vào bài đăng này để thấy các vấn đề với lập chỉ mục Datetime


6
Cả hai đều có cùng một vấn đề nếu bạn chọn một hàm dựa trên giá trị cột và cả hai đều có thể được lập chỉ mục.
Marcus Adams

4
Index hoạt động trên dấu thời gian và không hoạt động trên datetime? Bạn đã rút ra kết luận sai từ những bài viết.
Salman A

9

Tôi đã ngừng sử dụng datetimetrong các ứng dụng của mình sau khi gặp nhiều vấn đề và lỗi liên quan đến múi giờ. IMHO sử dụng timestamptốt hơn datetimetrong hầu hết các trường hợp .

Khi bạn hỏi mấy giờ rồi? và câu trả lời giống như '2019-02-05 21:18:30', chưa hoàn thành, không được xác định câu trả lời vì nó thiếu một phần khác, trong múi giờ nào? Washington? Matxcơva? Bắc Kinh ?

Sử dụng thời gian không có múi giờ có nghĩa là ứng dụng của bạn chỉ xử lý 1 múi giờ, tuy nhiên dấu thời gian mang lại cho bạn những lợi ích của datetime cộng với tính linh hoạt của việc hiển thị cùng một thời điểm chính xác trong các múi giờ khác nhau.

Dưới đây là một số trường hợp sẽ khiến bạn hối hận khi sử dụng datetimevà ước rằng bạn đã lưu trữ dữ liệu của mình trong dấu thời gian.

  1. Để khách hàng của bạn thoải mái, bạn muốn cho họ thấy thời gian dựa trên múi giờ ưa thích của họ mà không khiến họ phải làm toán và chuyển đổi thời gian sang múi giờ có ý nghĩa của họ. tất cả những gì bạn cần là thay đổi múi giờ và tất cả mã ứng dụng của bạn sẽ giống nhau. (Trên thực tế, bạn phải luôn xác định múi giờ khi bắt đầu ứng dụng hoặc yêu cầu xử lý trong trường hợp ứng dụng PHP)

    SET time_zone = '+2:00';
  2. bạn đã thay đổi quốc gia bạn ở và tiếp tục công việc duy trì dữ liệu trong khi xem dữ liệu đó ở múi giờ khác (không thay đổi dữ liệu thực tế).

  3. bạn chấp nhận dữ liệu từ các khách hàng khác nhau trên khắp thế giới, mỗi người trong số họ chèn thời gian vào múi giờ của mình.

Nói ngắn gọn

datetime = application hỗ trợ 1 múi giờ (cho cả chèn và chọn)

timestamp = ứng dụng hỗ trợ bất kỳ múi giờ nào (cho cả chèn và chọn)


Câu trả lời này chỉ dành cho việc làm nổi bật tính linh hoạt và dễ dàng của dấu thời gian khi nói đến múi giờ, nó không bao gồm bất kỳ sự khác biệt nào khác như kích thước hoặc phạm vi hoặc phân số cột .


nếu có các trường sử dụng datevà các trường khác sử dụng timestamptrong một bảng. Tôi nghĩ rằng nó sẽ gây ra sự cố mới vì dữ liệu được lọc theo wherekhông phù hợp với thay đổi của múi giờ.
Erlang P

@ErlangP Trong trường hợp đó, ứng dụng của bạn sẽ khắc phục sự cố múi giờ trên datecột trước khi gửi truy vấn.
Kế toán م

7

Tôi thích sử dụng dấu thời gian để giữ mọi thứ ở một định dạng thô phổ biến và định dạng dữ liệu theo mã PHP hoặc trong truy vấn SQL của bạn. Có những trường hợp nó có ích trong mã của bạn để giữ mọi thứ trong vài giây.



6

Tôi thích một dấu thời gian Unix, bởi vì bạn có thể chuyển đổi thành số và chỉ cần lo lắng về số lượng. Ngoài ra, bạn thêm / bớt và nhận thời lượng, vv Sau đó chuyển đổi kết quả thành Ngày ở bất kỳ định dạng nào. Mã này tìm ra bao nhiêu thời gian tính bằng phút trôi qua giữa dấu thời gian từ tài liệu và thời gian hiện tại.

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);

4
Hoặc, sử dụng một datetime MySQL có thể đọc và bản địa của con người, và sử dụng các hàm MySQL gốc để thêm / trừ dữ liệu.
Julien Palard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.