Czy zaleciłbyś użycie pola datetime lub datownika i dlaczego (używając MySQL)?
Pracuję z PHP po stronie serwera.
Czy zaleciłbyś użycie pola datetime lub datownika i dlaczego (używając MySQL)?
Pracuję z PHP po stronie serwera.
Odpowiedzi:
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.
DATETIME
reprezentuje datę (zgodnie z kalendarzem) i godzinę (co można zaobserwować na zegarze ściennym), podczas gdy TIMESTAMP
reprezentuje 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].
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 .
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.
new Date().getTime()
daje już wartość 64-bitową.
Poniższe przykłady pokazują, jak TIMESTAMP
typ data zmienił wartości po zmianie time-zone to 'america/new_york'
gdzie DATETIME
jest 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 .
DATETIME
czas zmienił się wraz ze zmianą strefy czasowej, TIMESTAMP
nie zmienił się, ale zmieniła się ludzka reprezentacja.
set time_zone="america/new_york"
;
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).
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.
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:
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.
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;)
TIMESTAMP to cztery bajty vs osiem bajtów dla DATETIME.
Znaczniki czasu są również jaśniejsze w bazie danych i szybciej indeksowane.
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.
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.
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
SET time_zone = '+0:00';
dla UTC.
timestamp
Pole jest szczególnym przypadkiem na datetime
polu. Możesz tworzyć timestamp
kolumny, aby mieć specjalne właściwości; można ustawić, aby aktualizował się sam podczas tworzenia i / lub aktualizacji.
W „większej” bazie danych timestamp
zawiera kilka specjalnych przypadków.
To, co jest właściwe, zależy całkowicie od tego, co chcesz zrobić.
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 = ...
).
Porównanie DATETIME, TIMESTAMP i DATE
Co to jest [frakcja]?
Źródła:
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.
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();
.
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 user
tabelę z polem DATA REJESTRACJI . W tej user
tabeli, 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;
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 .
SET time_zone = '+0:00';
(tutaj UTC), aby mieć pewność, co otrzymujesz / ustawiasz na podstawie TIMESTAMP
wartości i unikaj zależnie od domyślnej strefy czasowej serwera, która może się zmienić.
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.
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:
Z tych wszystkich powodów wybieram pola UTC i znacznik czasu, jeśli to możliwe. I unikam bólów głowy;)
warranties.expires_at
nie może być dzisiaj datownikiem MySQL.
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.
ON UPDATE CURRENT_TIMESTAMP
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 ′
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| 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. |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
Inną różnicą między datownikiem a datą jest datownik, którego domyślną wartością jest NULL.
CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
pierwsza kolumna może przyjmować wartość NULL.
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.
Główną różnicą jest
spójrz na ten post, aby zobaczyć problemy z indeksowaniem Datetime
Przestałem używać datetime
w swoich aplikacjach po napotkaniu wielu problemów i błędów związanych ze strefami czasowymi. Korzystanie z IMHO timestamp
jest lepsze niż datetime
w 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 datetime
i życzyłbyś sobie przechowywania danych w znacznikach czasu.
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';
zmieniłeś kraj, w którym przebywasz, i kontynuujesz pracę nad utrzymywaniem danych, obserwując je w innej strefie czasowej (bez zmiany rzeczywistych danych).
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 .
date
, i inne zastosowania pól timestamp
w jednej tabeli. Myślę, że spowoduje to nowy problem, ponieważ filtrowane dane where
nie są zgodne ze zmianami strefy czasowej.
date
kolumnie przed wysłaniem zapytania.
A TIMESTAMP
wymaga 4 bajtów, podczas gdy a DATETIME
wymaga 8 bajtów.
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);