Czy w MySQL powinienem używać typu danych data-godzina lub datownik?

Odpowiedzi:

1829

Znaczniki czasu w MySQL są zwykle używane do śledzenia zmian w rekordach i często są aktualizowane przy każdej zmianie rekordu. Jeśli chcesz zapisać określoną wartość, powinieneś użyć pola daty i godziny.

Jeśli chciałeś zdecydować, czy chcesz użyć znacznika czasu UNIX, czy natywnego pola daty i godziny MySQL, wybierz format macierzysty. W ten sposób możesz wykonywać obliczenia w MySQL ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")i łatwo zmienić format wartości na znacznik czasu UNIX, ("SELECT UNIX_TIMESTAMP(my_datetime)")gdy zapytasz rekordu, jeśli chcesz na nim operować za pomocą PHP.

blivet
źródło
981
Ważną różnicą jest to, że DATETIMEreprezentuje datę (zgodnie z kalendarzem) i godzinę (co można zaobserwować na zegarze ściennym), podczas gdy TIMESTAMPreprezentuje dobrze określony moment w czasie. Może to być bardzo ważne, jeśli aplikacja obsługuje strefy czasowe. Jak dawno temu „2010-09-01 16:31:00”? To zależy od strefy czasowej, w której się znajdujesz. Dla mnie to było zaledwie kilka sekund temu, dla ciebie może to oznaczać czas w przyszłości. Jeśli powiem 1283351460 sekund od '1970-01-01 00:00:00 UTC', wiesz dokładnie, o której chwili mówię. (Zobacz doskonałą odpowiedź Nira poniżej). [Minusem: prawidłowy zakres].
MattBianco,
121
Kolejna różnica: zapytania z „natywną” datą nie będą buforowane, ale zapytania z datownikiem - będą.
OZ_
39
„Znaczniki czasu w MySQL są zwykle używane do śledzenia zmian w rekordach”. Nie sądzę, że to dobra odpowiedź. Znaczniki czasu są o wiele potężniejsze i bardziej skomplikowane, niż powiedzieli MattBianco i Nir. Chociaż druga część odpowiedzi jest bardzo dobra. To prawda, co powiedział blivet i jest to dobra rada.
Santiagobasulto
10
Również 1 ważna uwaga, DATETIME i TIMESTAMP mogą z szacunkiem używać CURRENT_TIMESTAMP, NOW () jako wartości domyślnej, ale na przykład DATE nie, ponieważ domyślnie używa „0000-00-00”, więc aby rozwiązać ten problem, należy napisać Twój własny wyzwalacz do tej tabeli, aby wstawić bieżącą datę (bez czasu) w polu / kolumnie z typem mysql DATE.
Arthur Kushman
14
@DavidHarkness: Dokumentacja mówi: „Aby określić właściwości automatyczne, użyj klauzul DEFAULT CURRENT_TIMESTAMP i ON UPDATE CURRENT_TIMESTAMP” dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
Plap
917

W MySQL 5 i nowszych wartości TIMESTAMP są konwertowane z bieżącej strefy czasowej na UTC w celu przechowywania i konwertowane z powrotem z UTC do bieżącej strefy czasowej w celu pobrania. (Dzieje się tak tylko w przypadku typu danych TIMESTAMP, a nie w przypadku innych typów, takich jak DATETIME.)

Domyślnie bieżąca strefa czasowa dla każdego połączenia to czas serwera. Strefę czasową można ustawić dla poszczególnych połączeń, zgodnie z opisem w sekcji Obsługa stref czasowych serwera MySQL .

Nir
źródło
11
ta prezentacja OReilly jest bardzo dobra dla tego tematu (plik PDF przepraszam) cdn.oreillystatic.com/en/assets/1/event/36/…
gcb
13
Chodzi również o charakter wydarzenia: - Wideokonferencja (TIMESTAMP). Wszyscy uczestnicy powinni zobaczyć odniesienie do bezwzględnej chwili czasu dostosowanej do strefy czasowej. - Lokalny czas zadania (DATETIME), powinienem wykonać to zadanie o godzinie 2014/03/31 9:00 rano, bez względu na to, czy tego dnia pracuję w Nowym Jorku czy Paryżu. Zacznę pracować o 8:00 czasu lokalnego, w którym będę.
yumper
1
Więc jeśli ZMIENĘ strefę czasową serwera, to wartość TIMESTAMP pozostanie taka sama, czy też się zmieni?
Andrew
3
@Andrew, ponieważ jest to UTC, pozostanie UTC. Jednak konwersja wsteczna zmieni się na „nową” strefę czasową serwera.
nembleton
@yucer - Nie polecam myśleć o tym w ten sposób. Najbardziej konsekwentnym zastosowaniem w globalnej gospodarce jest konwersja wszystkich czasów danych na UTC w celu przechowywania. Umownie traktuj Datetime jako pole UTC. Obciąża to wszystkie zadania, które wprowadzają czasy danych, aby dokonać konwersji na UTC, ale jest to czystsza konstrukcja długoterminowa. Oczywiście przedstaw informacje użytkownikowi na podstawie jego bieżących ustawień. Jeśli użytkownik chce wprowadzić „09:00 w Paryżu”, pozwól mu ustawić czas w Paryżu, a następnie wprowadź 09:00. Wówczas każdy, kto jest w Nowym Jorku, może łatwo znaleźć godzinę, o której musi się obudzić, aby się telekonferencji.
ToolmakerSteve
524

Zawsze używam pól DATETIME do innych celów niż metadane wierszy (data utworzenia lub modyfikacji).

Jak wspomniano w dokumentacji MySQL:

Typ DATETIME jest używany, gdy potrzebne są wartości zawierające zarówno datę, jak i godzinę. MySQL pobiera i wyświetla wartości DATETIME w formacie „RRRR-MM-DD GG: MM: SS”. Obsługiwany zakres to „1000-01-01 00:00:00” do „9999-12-31 23:59:59”.

...

Typ danych TIMESTAMP ma zakres od „1970-01-01 00:00:01” UTC do „2038-01-09 03:14:07” UTC. Ma różne właściwości, w zależności od wersji MySQL i trybu SQL, w którym działa serwer.

Prawdopodobnie osiągniesz dolny limit TIMESTAMP w powszechnym użyciu - np. Przechowywanie daty urodzin.

scronid
źródło
195
możesz również łatwo przekroczyć górny limit, jeśli prowadzisz bankowość lub nieruchomości ... 30-letnie kredyty hipoteczne wykraczają teraz poza 2038 r.
Kip 10'12
16
Oczywiście używaj 64-bitowych znaczników czasu Unix. Na przykład w Javie new Date().getTime()daje już wartość 64-bitową.
osa
5
+1 dla DATETIME: W naszym przepływie danych, z SQL Server sklepu fizycznego do zakupu i faktury, przeniesione do MySQL Server dla sklepu wirtualnego na stronie internetowej, DATETIME jest lepszy do modyfikacji daty i godziny, ponieważ ten typ danych istnieje również w Transact -SQL. Ale TIMESTAMP oznacza inną rzecz w Transact-SQL, jest Binarny jak ROWVERSION, chociaż MySQL TIMESTAMP jest podobny do DateTime. Unikamy więc użycia TIMESTAMP do kompatybilności dwóch DB.
jacouh
10
Brak pomysłu. Jest to o wiele większy problem niż tylko MySQL i nie ma prostej poprawki: en.wikipedia.org/wiki/Year_2038_problem Nie wierzę, że MySQL może po prostu zadeklarować znaczniki czasu są teraz 64-bitowe i zakładam, że wszystko będzie dobrze. Nie kontrolują sprzętu.
scronide
5
Data urodzenia może być DATETIME, jeśli znasz godzinę urodzenia, tak jak ja dla mojej.
Kris Craig,
322

Poniższe przykłady pokazują, jak TIMESTAMPtyp data zmienił wartości po zmianie time-zone to 'america/new_york'gdzie DATETIMEjest niezmieniona.

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 |
+---------------------+---------------------+

Przekształciłem swoją odpowiedź w artykuł, aby więcej osób mogło znaleźć to przydatne, MySQL: Datetime vs. Datownik Typy danych .

mr_eclair
źródło
55
Właściwie rzeczywisty DATETIMEczas zmienił się wraz ze zmianą strefy czasowej, TIMESTAMPnie zmienił się, ale zmieniła się ludzka reprezentacja.
flindeberg
3
Wygląda na to, że to polecenie nie działa w MySQL 5.6 set time_zone="america/new_york";
Manjunath Reddy
Oto odpowiedź na problem z ustawioną strefą czasową. stackoverflow.com/questions/3451847/mysql-timezone-change
Manjunath Reddy
2
Zgadzam się z @flindeberg. Znacznik czasu reprezentuje poprawny czas, a nie datę / godzinę, po zmianie strefy czasowej
Nitin Bansal,
193

Główną różnicą jest to, że DATETIME jest stały, podczas gdy ustawienie ma wpływ na TIMESTAMP time_zone.

To ma znaczenie tylko wtedy, gdy masz - lub może w przyszłości - zsynchronizowałeś klastry w różnych strefach czasowych.

Mówiąc prościej: jeśli mam bazę danych w Australii i zrzucę tę bazę danych, aby zsynchronizować / wypełnić bazę danych w Ameryce, TIMESTAMP zaktualizuje się, aby odzwierciedlić rzeczywisty czas zdarzenia w nowej strefie czasowej, podczas gdy DATETIME nadal odzwierciedlają czas zdarzenia w strefie czasowej au .

Doskonałym przykładem użycia DATETIME tam, gdzie powinien być użyty TIMESTAMP, jest Facebook, gdzie ich serwery nigdy nie są do końca pewni, co się dzieje w różnych strefach czasowych. Kiedyś miałem rozmowę, w której czas powiedział, że odpowiadam na wiadomości, zanim wiadomość faktycznie została wysłana. (To oczywiście mogło być również spowodowane złym tłumaczeniem stref czasowych w oprogramowaniu do przesyłania wiadomości, gdyby godziny były publikowane, a nie synchronizowane).

ekerner
źródło
83
Nie sądzę, żeby to był dobry sposób myślenia. Przechowuję i przetwarzam wszystkie daty w UTC i upewniam się, że fronton wyświetla je zgodnie z podaną strefą czasową. To podejście jest proste i przewidywalne.
Kos
8
@Kos: czy przechowywanie i przetwarzanie wszystkich dat w UTC nie jest dokładnie tym, co robi TIMESTAMP wewnętrznie? (Konwertujesz go, by wyświetlał lokalną strefę czasową?)
karbokal.
10
moja lokalna strefa czasowa? Skąd twój DB wiedziałby o mojej strefie czasowej? ;-) Zwykle przetwarzanie danych między bazą danych a interfejsem użytkownika jest dość duże. Lokalizację wykonuję dopiero po całym przetwarzaniu.
Kos,
3
@Koz: moja baza danych nie zna strefy czasowej baz danych:! Ale zna znacznik czasu. Twoja baza danych zna własne ustawienie strefy czasowej i stosuje to podczas interpretacji / reprezentowania znacznika czasu. 01:01 w dniu 11 grudnia 2013 r. W Pekinie Chiny to nie ten sam moment, co 01:01 w dniu 11 grudnia 2013 r. W Sydney w Australii. Google: „strefy czasowe” i „główny południk”.
ekerner,
2
MySQL konwertuje wartości TIMESTAMP z bieżącej strefy czasowej na UTC w celu przechowywania i z powrotem z UTC do bieżącej strefy czasowej w celu pobrania. (Nie dotyczy to innych typów, takich jak DATETIME.) Dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo
124

Decyzję podejmuję na zasadzie semantycznej.

Używam znacznika czasu, kiedy muszę zapisać (mniej więcej) ustalony punkt w czasie. Na przykład, gdy rekord został wstawiony do bazy danych lub gdy miała miejsce akcja użytkownika.

Korzystam z pola daty i godziny, kiedy datę / godzinę można ustawić i zmienić dowolnie. Na przykład, gdy użytkownik może zapisać później zmienić spotkania.

MaxVT
źródło
znacznik czasu - ustalony punkt w czasie, skoordynowany uniwersalny czas danych - w stosunku do punktu widzenia, do odniesienia czasu (ej strefa czasowa czasu lokalnego), może być… skoordynowany czas lokalny?
yumper
110

Polecam nie używać pola DATETIME ani TIMESTAMP. Jeśli chcesz reprezentować konkretny dzień jako całość (na przykład urodziny), użyj typu DATA, ale jeśli jesteś bardziej szczegółowy, prawdopodobnie chcesz nagrać rzeczywisty moment, a nie jednostkę czas (dzień, tydzień, miesiąc, rok). Zamiast używać DATETIME lub TIMESTAMP, użyj BIGINT i po prostu zapisz liczbę milisekund od epoki (System.currentTimeMillis (), jeśli używasz Java). Ma to kilka zalet:

  1. Unikasz blokady dostawcy. Prawie każda baza danych obsługuje liczby całkowite w stosunkowo podobny sposób. Załóżmy, że chcesz przejść do innej bazy danych. Czy chcesz się martwić różnicami między wartościami DATETIME MySQL a tym, jak Oracle je definiuje? Nawet wśród różnych wersji MySQL TIMESTAMPS mają inny poziom precyzji. Dopiero niedawno MySQL obsługiwał milisekundy w znacznikach czasu.
  2. Brak problemów ze strefą czasową. Pojawiły się wnikliwe komentarze na temat tego, co dzieje się w strefach czasowych z różnymi typami danych. Ale czy ta wiedza jest powszechna i czy wszyscy współpracownicy poświęcą trochę czasu, aby się jej nauczyć? Z drugiej strony dość trudno jest zepsuć BigINT w java.util.Date. Użycie BIGINT powoduje, że wiele problemów ze strefami czasowymi spada na margines.
  3. Bez obaw o zasięg lub precyzję. Nie musisz się martwić o to, co zostanie skrócone przez przyszłe zakresy dat (TIMESTAMP idzie tylko do 2038 r.).
  4. Integracja narzędzi innych firm. Korzystanie z liczby całkowitej jest proste w przypadku narzędzi innych firm (np. EclipseLink) do połączenia z bazą danych. Nie każde narzędzie innej firmy będzie miało takie samo rozumienie „daty i godziny”, jak MySQL. Chcesz się dowiedzieć w Hibernacji, czy powinieneś użyć obiektu java.sql.TimeStamp czy java.util.Date, jeśli używasz tych niestandardowych typów danych? Używanie podstawowych typów danych sprawia, że ​​korzystanie z narzędzi innych firm jest banalne.

Ten problem jest ściśle związany ze sposobem przechowywania wartości pieniężnej (tj. 1,99 USD) w bazie danych. Czy powinieneś użyć wartości dziesiętnej, bazy danych typu Pieniądze, a najgorszego ze wszystkich podwójnych? Wszystkie 3 z tych opcji są okropne z wielu tych samych powodów wymienionych powyżej. Rozwiązaniem jest przechowywanie wartości pieniędzy w centach za pomocą BIGINT, a następnie przeliczanie centów na dolary po wyświetleniu wartości użytkownikowi. Zadaniem bazy danych jest przechowywanie danych, a NIE ich interpretacja. Wszystkie te fantazyjne typy danych, które widzisz w bazach danych (zwłaszcza Oracle), niewiele dodają i rozpoczynają drogę do blokady dostawcy.

użytkownik64141
źródło
12
Podoba mi się to rozwiązanie. Ważnym problemem jest TIMESTAMP wygasający w 2038 r. To nie jest tak daleko!
Charlie Dalsass,
4
@CharlieDalsass Czy uważasz, że obecne oprogramowanie będzie tam w tym czasie :-P
Habeeb Perwad
13
Utrudnia to wyszukiwanie danych według daty, jeśli są one przechowywane w milisekundach
Ali Saeed,
4
To naprawdę najlepsze rozwiązanie, jeśli zależy Ci na przenośności i obsłudze użytkowników w wielu strefach czasowych lub bazy danych w innej strefie czasowej niż użytkownicy. TIMESTAMP może być dobrym rozwiązaniem, jeśli nie ma wad projektowych. Szkoda, że ​​zepsute rozwiązania uzyskały więcej głosów, ponieważ zostały opublikowane wcześnie (lata!).
Niemiecki
4
Doskonałe rozwiązanie! I masz rację, że jesteś „zamknięty”. Kiedy przyzwyczaisz się, że pozwalasz innym „wykonywać pracę za ciebie”, wtedy zaczynasz tracić części, które sprawiają, że TY jesteś programistą.
fmc
98

TIMESTAMP ma 4 bajty i 8 bajtów dla DATETIME.

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

Ale jak powiedział scronide, ma dolną granicę roku 1970. Jest świetny na wszystko, co może się zdarzyć w przyszłości;)

Alex
źródło
185
Przyszłość kończy się o 2038-01-19 03:14:07 UTC.
MattBianco,
5
To głupie. Myślałem, że typ TIMESTAMP będzie „gotowy na przyszłość”, ponieważ jest stosunkowo nowy. Nie możesz zawracać sobie głowy konwersją datetime na UTC i cofać się za każdym razem, gdy pracujesz w różnych strefach czasowych. Powinny one zwiększyć TIMESTAMP .. co najmniej 1 bajt większy. doda 68 * 255 = 17340 lat więcej ... chociaż nie będzie 32-bitowy.
NickSoft
10
Czy wiesz, dlaczego termin TIMESTAMP kończy się w 2038 roku? Ponieważ jest to liczba całkowita, a liczby całkowite mają limit, który wynosi 2147483647. Myślę, że to jest powód. Być może, jeśli zmienią jego typ na varchar i zmienią sposób manipulowania nim, będzie on „gotowy na przyszłość”.
vinsa,
6
@ vinsa, nie sądzę, że do tego czasu będzie gotowy. Nadal pamiętasz błąd Y2K? Nadchodzi 2038 rok.
Pacerier,
2
Do 2038 r. MySQL (jeśli nadal istnieje) po prostu zaktualizuje pole TIMESTAMP, aby używało więcej niż 4 bajtów i pozwoliło na szerszy zakres
the_nuts
95
  1. TIMESTAMP to cztery bajty vs osiem bajtów dla DATETIME.

  2. Znaczniki czasu są również jaśniejsze w bazie danych i szybciej indeksowane.

  3. Typ DATETIME jest używany, gdy potrzebne są wartości zawierające zarówno datę, jak i godzinę. MySQL pobiera i wyświetla wartości DATETIME w formacie „RRRR-MM-DD GG: MM: SS”. Obsługiwany zakres to „1000-01-01 00:00:00 ′ do„ 9999-12-31 23:59:59 ′.

Typ danych TIMESTAMP ma zakres od „1970-01-01 00:00:01 ′ UTC do„ 2038-01-09 03:14:07 ′ UTC. Ma różne właściwości, w zależności od wersji MySQL i trybu SQL, w którym działa serwer.

  1. DATETIME jest stały, a TIMESTAMP ma wpływ na ustawienie strefy czasowej.
Vivek S.
źródło
6
Musisz wyjaśnić # 4: Zapisany znacznik czasu jest stały i nie jest względny (całkowicie agnostyczny) do strefy czasowej, podczas gdy na wynik wyświetlany podczas pobierania ma wpływ strefa czasowa żądającej sesji. DATETIME jest zawsze zależne od strefy czasowej, w której zostało zarejestrowane, i zawsze należy brać pod uwagę w tym kontekście, odpowiedzialność spoczywającą teraz na aplikacji.
Christopher McGowan
1
Świetna odpowiedź. Aby dodać do tej odpowiedzi, jeśli spróbujemy przechowywać wartości poza tym „2038-01-09 03:14:07”, albo otrzymamy błąd, albo zostanie on zapisany jako „0000-00-00 00:00:00”. Otrzymałem ten błąd dla mojej bazy danych, ponieważ ma ona przesunięte w czasie wartości (dla celów szyfrowania).
KarthikS
Występuje również problem z wartością DATETIME z wartością DOMYŚLNĄ w wersjach mysql poniżej 5.5. dba.stackexchange.com/questions/132951/…
Velaro
47

Tak naprawdę zależy od zastosowania.

Rozważ ustawienie znacznika czasu przez użytkownika na serwerze w Nowym Jorku, aby umówić się na spotkanie w Sanghai. Teraz, gdy użytkownik łączy się w Sanghai, uzyskuje dostęp do tego samego znacznika czasu spotkania z serwera lustrzanego w Tokio. Zobaczy spotkanie w czasie Tokio, przesunięte w stosunku do pierwotnego czasu nowojorskiego.

Dlatego w przypadku wartości reprezentujących czas użytkownika, takich jak spotkanie lub harmonogram, data i godzina są lepsze. Pozwala użytkownikowi kontrolować dokładną datę i godzinę, niezależnie od ustawień serwera. Ustawiony czas to ustawiony czas, na który nie ma wpływu strefa czasowa serwera, strefa czasowa użytkownika ani zmiany w sposobie obliczania czasu letniego (tak, to się zmienia).

Z drugiej strony, dla wartości reprezentujących czas systemowy, takich jak transakcje płatnicze, modyfikacje tabeli lub rejestrowanie, zawsze używaj znaczników czasu. Przeniesienie serwera do innej strefy czasowej lub porównanie między serwerami w różnych strefach czasowych nie będzie miało wpływu na system.

Znaczniki czasu są również jaśniejsze w bazie danych i szybciej indeksowane.

Ianaré
źródło
Twoja aplikacja nie powinna opierać się na strefie czasowej serwera. Aplikacja powinna ZAWSZE wybierać strefę czasową w sesji połączenia z bazą danych, z której korzysta, przed wydaniem zapytania. Jeśli połączenie jest współużytkowane przez wielu użytkowników (np. Webapp), użyj UTC i wykonaj konwersję strefy czasowej po stronie renderowania.
dolmen
42

2016+ : radzę ustawić strefę czasową MySQL na UTC i użyć DATETIME:

Wszelkie najnowsze fronty frontu (Angular 1/2, reaguj, Vue, ...) mogą łatwo i automatycznie konwertować datę i godzinę UTC na czas lokalny.

Dodatkowo:

(Chyba że prawdopodobnie zmienisz strefę czasową swoich serwerów)


Przykład z 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' }}

Wszystkie zlokalizowane formaty czasu są dostępne tutaj: https://docs.angularjs.org/api/ng/filter/date

Sebastien Horin
źródło
8
Twoje dane nie powinny być dołączane do ustawień strefy czasowej twoich serwerów. Może działa na ciebie, jeśli masz jedno biurko MySql pod biurkiem
Jin
@Jin UTC oznacza brak strefy czasowej jak TIMESTAMP. Jeśli wszystkie twoje serwery są w UTC, nie ma żadnych problemów. Może to nie działa, jeśli masz konfigurację z 2000 roku.
Sebastien Horin
TIMESTAMP może zostać w przyszłości zaktualizowany do 64-bitowej wartości. Nie ma już problemu.
twicejr
Ładowanie całych bibliotek innych firm w celu przechwycenia czegoś takiego nie może być zbyt dobre pod względem wydajności, prawda? Biorąc pod uwagę, że jest to po stronie klienta i nie wpływa na bazę danych ... Mimo wszystko, wszystko, co robisz w interfejsie, BĘDZIE wymagało kontroli na serwerze. Myśląc o pełnym obrazie, czy to naprawdę pomaga w kwestii prędkości? - Nawiasem mówiąc, te testy są trochę dziwne. Używanie ciągu w zapytaniu do porównywania pól znaczników czasu również wydaje się dość dziwne. To musi również zaszkodzić wydajności, prawda?
NoobishPro,
1
Nie polegaj w swojej aplikacji na strefie czasowej serwera. Zamiast tego zdefiniuj strefę czasową, która ma być używana przy każdym połączeniu z bazą danych: SET time_zone = '+0:00';dla UTC.
dolmen
37

timestampPole jest szczególnym przypadkiem na datetimepolu. Możesz tworzyć timestampkolumny, aby mieć specjalne właściwości; można ustawić, aby aktualizował się sam podczas tworzenia i / lub aktualizacji.

W „większej” bazie danych timestampzawiera kilka specjalnych przypadków.

To, co jest właściwe, zależy całkowicie od tego, co chcesz zrobić.

Jeff Warnica
źródło
6
Nie, różnica polega nie tylko na „specjalnym przypadku”. Ponieważ strefy czasowe sesji, które ustawiają / wysyłają zapytania, wartości są zaangażowane w różny sposób.
dolmen
Cieszę się, że wpisałeś: „To, co jest właściwe, zależy całkowicie od tego, co chcesz zrobić”. Istnieje zbyt wiele odpowiedzi na SE, że stan, bez wystarczającego uzasadnienia, „Musisz nigdy zrobienia X” lub „Musisz zawsze zrobić Y”.
Agi Hammerthief
37

TIMESTAMP jest zawsze w UTC (to znaczy upłynęło sekund od 1970-01-01, w UTC), a twój serwer MySQL automatycznie konwertuje go na datę / czas dla strefy czasowej połączenia. W dłuższej perspektywie TIMESTAMP to droga, ponieważ wiesz, że Twoje dane czasowe zawsze będą w UTC. Na przykład nie zmarnujesz swoich dat, jeśli przeprowadzisz migrację na inny serwer lub zmienisz ustawienia strefy czasowej na serwerze.

Uwaga: domyślną strefą czasową połączenia jest strefa czasowa serwera, ale można ją (należy) zmienić na sesję (patrz SET time_zone = ...).

Sobes
źródło
29

Porównanie DATETIME, TIMESTAMP i DATE

wprowadź opis zdjęcia tutaj

Co to jest [frakcja]?

  • Wartość DATETIME lub TIMESTAMP może zawierać końcową część ułamkową sekundy z dokładnością do mikrosekund (6 cyfr). W szczególności każda część ułamkowa w wartości wstawionej do kolumny DATETIME lub TIMESTAMP jest przechowywana, a nie odrzucana. Jest to oczywiście opcjonalne.

Źródła:

Dehan de Croos
źródło
24

Warto zauważyć, że w MySQL podczas tworzenia kolumn tabeli można użyć czegoś podobnego do poniższego:

on update CURRENT_TIMESTAMP

Spowoduje to aktualizację czasu za każdym razem, gdy modyfikujesz wiersz, i czasami jest bardzo pomocna przy przechowywaniu informacji o ostatniej edycji. Działa to tylko ze znacznikiem czasu, a nie datetime.

leejmurphy
źródło
23

Zawsze używałbym uniksowego znacznika czasu podczas pracy z MySQL i PHP. Głównym powodem tego, że jest to domyślna metoda daty w PHP, jest znacznik czasu jako parametr, więc nie będzie potrzeby analizowania.

Aby uzyskać bieżący uniksowy znacznik czasu w PHP, po prostu zrób time();
i MySQL SELECT UNIX_TIMESTAMP();.

Mark Davidson
źródło
6
-1 Właściwie uważam, że odpowiedź poniżej jest lepsza - użycie datetime pozwala na przekazanie większej logiki przetwarzania danych do samego MySQL, co może być bardzo przydatne.
Toby Hede
Czy nie było testów porównawczych pokazujących, że sortowanie w MySQL jest wolniejsze niż w php?
sdkfasldf
cóż, to zależy, czasem dobrze jest go używać, gdy nie chcemy używać strtotime. (php5.3 dep)
Adam Ramadhan
możesz wcisnąć logikę do mysql, używając w razie potrzeby
FROM_UNIXTIME
Kiedyś używałem wszystkich uniksowych znaczników czasu w moich aplikacjach PHP i MySQL, jednak uważam, że wygodniej jest przechowywać daty i godziny w MySQL jako rodzime typy dat / godzin. Jest to szczególnie przydatne do celów raportowania i po prostu przeglądania zestawów danych. Z czasem, gdy byłem sfrustrowany koniecznością kopiowania / przekraczania znaczników czasu Unixa, zacząłem się przełączać. Jestem całkiem pewien, że istnieje wydajność i inne zalety / wady, ale w zależności od przypadku użycia wygoda może być ważniejsza niż dość mikrooptymalizacje.
DavidScherer
17

Z moich doświadczeń wynika, że ​​jeśli chcesz, aby pole daty, w którym wstawianie odbywało się tylko raz, i nie chcesz mieć żadnych aktualizacji ani żadnych innych działań na tym polu, wybierz datę i godzinę .

Rozważmy na przykład usertabelę z polem DATA REJESTRACJI . W tej usertabeli, jeśli chcesz poznać czas ostatniego zalogowania konkretnego użytkownika, przejdź do pola typu znacznik czasu , aby pole zostało zaktualizowane.

Jeśli tworzysz tabelę z phpMyAdmin, ustawienie domyślne zaktualizuje pole znacznika czasu, gdy nastąpi aktualizacja wiersza. Jeśli Twój plik znacznika czasu nie aktualizuje się wraz z aktualizacją wiersza, możesz użyć następującego zapytania, aby pole znacznika czasu było automatycznie aktualizowane.

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Kannan Prasad
źródło
15

Typ danych sygnatury czasowej przechowuje datę i godzinę, ale w formacie UTC, a nie w bieżącym formacie strefy czasowej, jak robi to datetime. A kiedy pobierasz dane, znacznik czasu ponownie konwertuje to na bieżący czas strefy czasowej.

Załóżmy, że jesteś w USA i pobierasz dane z serwera, który ma strefę czasową USA. Następnie otrzymasz datę i godzinę zgodnie ze strefą czasową USA. Kolumna typu danych znacznika czasu zawsze jest aktualizowana automatycznie, gdy wiersz jest aktualizowany. Przydatne może być więc śledzenie, kiedy konkretny wiersz był ostatnio aktualizowany.

Aby uzyskać więcej informacji, przeczytaj post na blogu Timestamp Vs Datetime .

Arvind
źródło
Możesz (powinieneś) zawsze definiować strefę czasową na poziomie sesji za pomocą SET time_zone = '+0:00';(tutaj UTC), aby mieć pewność, co otrzymujesz / ustawiasz na podstawie TIMESTAMPwartości i unikaj zależnie od domyślnej strefy czasowej serwera, która może się zmienić.
dolmen,
14

Zawsze używam uniksowego znacznika czasu, po prostu w celu zachowania rozsądku, gdy mamy do czynienia z dużą ilością informacji dotyczących czasu, zwłaszcza podczas dokonywania korekt dla stref czasowych, dodawania / odejmowania dat i tym podobnych. Podczas porównywania znaczników czasu wyklucza to skomplikowane czynniki strefy czasowej i pozwala zaoszczędzić zasoby w przetwarzaniu po stronie serwera (niezależnie od tego, czy jest to kod aplikacji czy zapytania do bazy danych), ponieważ używa się lekkiej arytmetyki zamiast cięższego dodawania / odejmowania daty i czasu Funkcje.

Kolejna rzecz warta rozważenia:

Jeśli tworzysz aplikację, nigdy nie wiesz, w jaki sposób Twoje dane mogą być wykorzystane w dalszej kolejności. Jeśli skończysz na, powiedzmy, porównaniu szeregu rekordów w zestawie danych, powiedzmy, zbiorze elementów z interfejsu API innej firmy i powiedz, że ustawisz je w porządku chronologicznym, z przyjemnością będziesz mieć Uniksowe znaczniki czasu dla twoich wierszy. Nawet jeśli zdecydujesz się użyć znaczników czasu MySQL, przechowuj znacznik czasu Unix jako ubezpieczenie.

Oliver Holmberg
źródło
14

W moim przypadku ustawiam UTC jako strefę czasową dla wszystkiego: systemu, serwera bazy danych itp. Za każdym razem, kiedy mogę. Jeśli mój klient potrzebuje innej strefy czasowej, konfiguruję ją w aplikacji.

Prawie zawsze wolę znaczniki czasu niż pola daty i godziny, ponieważ znaczniki czasu domyślnie obejmują strefę czasową. Ponieważ więc od momentu, gdy aplikacja będzie dostępna dla użytkowników z różnych stref czasowych, a Ty chcesz, aby zobaczyli daty i godziny w lokalnej strefie czasowej, ten typ pola ułatwia to, niż gdyby dane zostały zapisane w polach daty i godziny .

Na plus, w przypadku migracji bazy danych do systemu z inną strefą czasową, czułbym się pewniej, korzystając ze znaczników czasu. Nie mówiąc już o możliwych problemach przy obliczaniu różnic między dwoma momentami, przy czym suma czasu zmienia się pomiędzy i wymaga dokładności 1 godziny lub mniej.

Podsumowując, cenię te zalety znacznika czasu:

  • gotowy do użycia w aplikacjach międzynarodowych (strefa czasowa)
  • łatwe migracje między strefami czasowymi
  • dość łatwe do obliczenia różnice (wystarczy odjąć oba znaczniki czasu)
  • nie martw się datami w okresie letnim

Z tych wszystkich powodów wybieram pola UTC i znacznik czasu, jeśli to możliwe. I unikam bólów głowy;)

Roger Campanera
źródło
dane znacznika czasu będą zabawne dla osoby obsługującej Twoją aplikację, gdy nadejdzie 20 stycznia 2038 r. tik tik tik tik
Wilson Hauck
Typ znacznika czasu można następnie zwiększyć nieco i podwoić możliwe wartości.
Roger Campanera
Przetestuj swoją teorię, aby „trochę wzrosnąć” i sprawdź, czy możesz z powodzeniem przechowywać 1 lutego 2038 r. I odzyskać ją za pomocą MySQL. Po zakończeniu zobaczmy definicję tabeli. Prawdopodobnie będziesz mieć wielu nieszczęśliwych znajomych z przeszłości w lutym 2038 r.
Wilson Hauck
1
@WilsonHauck Będziesz musiał zaktualizować wersję MySQL na długo przed 2038 rokiem. A ten rozszerzony TIMESTAMP zostanie obsłużony przez migrację. Poza tym niewiele wniosków, oprócz obsługi hipotek, naprawdę wymaga teraz około 2038 r.
dolmen
@dolmen wiele profesjonalnych narzędzi i materiałów ma ponad 20-letnią gwarancję. Więc coś takiego warranties.expires_atnie może być dzisiaj datownikiem MySQL.
alexw
13

Uważaj na zmianę znacznika czasu podczas wykonywania instrukcji UPDATE w tabeli. Jeśli masz tabelę z kolumnami „Nazwa” (varchar), „Wiek” (int) i „Data_dodana” (znacznik czasu) i uruchomisz następującą instrukcję DML

UPDATE table
SET age = 30

wówczas każda pojedyncza wartość w kolumnie „Data dodana” zostałaby zmieniona na bieżący znacznik czasu.

Lloyd Banks
źródło
3
w zależności od konfiguracji stołu możesz kontrolować to zachowanie. spójrz na dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Charles
5
@CharlesFaiga Domyślne zachowanie polega na tym, że znacznik czasu jest aktualizowany po aktualizacji dowolnej innej kolumny. Musisz jawnie to wyłączyć, jeśli chcesz, aby znacznik czasu zachował swoją pierwotną wartość
Lloyd Banks
Co to jest ?! musisz ustawić kolumnę znacznika czasu naON UPDATE CURRENT_TIMESTAMP
Księgowy م
Jest to funkcja , którą należy wyraźnie włączyć podczas tworzenia tabeli.
dolmen
13

Odniesienie zaczerpnięte z tego artykułu:

Główne różnice:

TIMESTAMP służy do śledzenia zmian w rekordach i aktualizuje się za każdym razem, gdy rekord jest zmieniany. DATETIME służy do przechowywania określonej i statycznej wartości, na którą nie mają wpływu żadne zmiany w rekordach.

TIMESTAMP ma również wpływ na inne ustawienia związane ze STREFA CZASU. DATETIME jest stały.

TIMESTAMP wewnętrznie przekonwertował bieżącą strefę czasową na UTC w celu przechowywania, a podczas wyszukiwania konwertował z powrotem do bieżącej strefy czasowej. DATETIME nie może tego zrobić.

Obsługiwany zakres TIMESTAMP: „1970-01-01 00:00:01 ′ UTC do„ 2038-01-19 03:14:07 ”UTC Obsługiwany zakres DATETIME:„ 1000-01-01 00:00:00 ′ do „9999 -12-31 23:59:59 ′

Anvesh
źródło
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.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
Premraj
źródło
10

Inną różnicą między datownikiem a datą jest datownik, którego domyślną wartością jest NULL.

ecleel
źródło
8
To oczywiście źle. Oto przykład: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); pierwsza kolumna może przyjmować wartość NULL.
Ormoz
10

Znalazłem niezrównaną użyteczność w zdolności TIMESTAMP do automatycznej aktualizacji na podstawie bieżącego czasu bez użycia niepotrzebnych wyzwalaczy. Ale to tylko ja, chociaż TIMESTAMP to UTC, jak już powiedziano.

Może śledzić różne strefy czasowe, więc jeśli chcesz na przykład wyświetlić czas względny, czas UTC jest tym, czego chcesz.

Marc DiMillo
źródło
9

Główną różnicą jest

  • INDEKS na znaczniku czasu - działa
  • INDEKS na Datetime - nie działa

spójrz na ten post, aby zobaczyć problemy z indeksowaniem Datetime

Charles Faiga
źródło
6
Oba mają ten sam problem, jeśli wybierasz z funkcją opartą na wartości kolumny, i oba mogą być indeksowane.
Marcus Adams,
4
Indeks działa na sygnaturze czasowej i nie działa na datetime? Wyciągnąłeś błędne wnioski z tych postów.
Salman A
9

Przestałem używać datetimew swoich aplikacjach po napotkaniu wielu problemów i błędów związanych ze strefami czasowymi. Korzystanie z IMHO timestampjest lepsze niż datetimew większości przypadków .

Kiedy pytasz, która jest godzina? a odpowiedź pojawia się jako coś w stylu „2019-02-05 21:18:30”, która nie została ukończona, nie została zdefiniowana odpowiedź, ponieważ nie ma innej części, w której strefie czasowej? Waszyngtonie? Moskwie? Pekin?

Korzystanie z czasów danych bez strefy czasowej oznacza, że ​​aplikacja zajmuje się tylko 1 strefą czasową, jednak znaczniki czasu dają korzyści z datetime plus elastyczność wyświetlania tego samego dokładnego punktu czasowego w różnych strefach czasowych.

Oto kilka przypadków, w których będziesz żałować używania datetimei życzyłbyś sobie przechowywania danych w znacznikach czasu.

  1. Dla wygody klientów chcesz pokazywać im czasy na podstawie preferowanych stref czasowych, nie zmuszając ich do wykonywania obliczeń matematycznych i przekształcania czasu na znaczącą strefę czasową. wystarczy zmienić strefę czasową, a cały kod aplikacji będzie taki sam. (Właściwie należy zawsze definiować strefę czasową na początku aplikacji lub przetwarzać żądania w przypadku aplikacji PHP)

    SET time_zone = '+2:00';
  2. zmieniłeś kraj, w którym przebywasz, i kontynuujesz pracę nad utrzymywaniem danych, obserwując je w innej strefie czasowej (bez zmiany rzeczywistych danych).

  3. akceptujesz dane od różnych klientów na całym świecie, każdy z nich wstawia czas w swojej strefie czasowej.

W skrócie

datetime = aplikacja obsługuje 1 strefę czasową (zarówno dla wstawiania, jak i wybierania)

timestamp = aplikacja obsługuje dowolną strefę czasową (zarówno dla wstawiania, jak i wybierania)


Ta odpowiedź służy jedynie podkreśleniu elastyczności i łatwości znaczników czasowych, jeśli chodzi o strefy czasowe, ale nie obejmuje żadnych innych różnic, takich jak rozmiar kolumny, zakres lub ułamek .

Księgowy م
źródło
co jeśli istnieją pola, które używają date, i inne zastosowania pól timestampw jednej tabeli. Myślę, że spowoduje to nowy problem, ponieważ filtrowane dane wherenie są zgodne ze zmianami strefy czasowej.
Erlang P
@EllangP W takim przypadku aplikacja powinna naprawić problem strefy czasowej w datekolumnie przed wysłaniem zapytania.
Księgowy م
7

Wolę używać znacznika czasu, aby zachować wszystko w jednym wspólnym surowym formacie i sformatować dane w kodzie PHP lub w zapytaniu SQL. Są przypadki, w których przydaje się twój kod, aby wszystko utrzymywać w mgnieniu oka.

Hans
źródło
7

A TIMESTAMPwymaga 4 bajtów, podczas gdy a DATETIMEwymaga 8 bajtów.

Mwangi Thiga
źródło
6

Lubię uniksowy znacznik czasu, ponieważ możesz konwertować na liczby i martwić się o liczbę. Dodatkowo dodajesz / odejmujesz i otrzymujesz czasy trwania itp. Następnie przekonwertuj wynik na datę w dowolnym formacie. Ten kod dowiaduje się, ile czasu w minutach upłynęło między znacznikiem czasu z dokumentu, a bieżącym czasem.

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);
użytkownik723220
źródło
4
Możesz też użyć czytelnego dla ludzi i natywnego czasu MySQL oraz natywnych funkcji MySQL do dodawania / odejmowania czasów danych.
Julien Palard,