Dois-je utiliser le type de données datetime ou timestamp dans MySQL?

2685

Recommanderiez-vous d'utiliser un datetime ou un horodatage champ , et pourquoi (en utilisant MySQL)?

Je travaille avec PHP côté serveur.

karlipoppins
la source
1
ce qui a des informations pertinentes codeproject.com/Tips/1215635/MySQL-DATETIME-vs-TIMESTAMP
Waqleh
Si vous souhaitez que votre application soit interrompue en février 2038, utilisez l'horodatage. Vérifiez la plage de dates.
Wilson Hauck

Réponses:

1829

Les horodatages dans MySQL sont généralement utilisés pour suivre les modifications apportées aux enregistrements et sont souvent mis à jour chaque fois que l'enregistrement est modifié. Si vous souhaitez stocker une valeur spécifique, vous devez utiliser un champ datetime.

Si vous vouliez décider entre utiliser un horodatage UNIX ou un champ de date / heure MySQL natif, optez pour le format natif. Vous pouvez effectuer des calculs dans MySQL de cette façon ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")et il est simple de changer le format de la valeur en horodatage UNIX ("SELECT UNIX_TIMESTAMP(my_datetime)")lorsque vous interrogez l'enregistrement si vous souhaitez l'utiliser avec PHP.

blivet
la source
981
Une différence importante est qu'elle DATETIMEreprésente une date (telle que trouvée dans un calendrier) et une heure (comme on peut l'observer sur une horloge murale), tout en TIMESTAMPreprésentant un moment bien défini dans le temps. Cela peut être très important si votre application gère les fuseaux horaires. Il y a combien de temps '2010-09-01 16:31:00'? Cela dépend du fuseau horaire dans lequel vous vous trouvez. Pour moi, c'était il y a quelques secondes à peine, pour vous, cela pourrait représenter une époque future. Si je dis 1283351460 secondes depuis '1970-01-01 00:00:00 UTC', vous savez exactement de quel moment je parle. (Voir l'excellente réponse de Nir ci-dessous). [Inconvénient: plage valide].
MattBianco
121
Une autre différence: les requêtes avec datetime "natif" ne seront pas mises en cache, mais les requêtes avec horodatage - le seront.
OZ_
39
"Les horodatages dans MySQL sont généralement utilisés pour suivre les modifications apportées aux enregistrements" Ne pensez pas que ce soit une bonne réponse. L'horodatage est beaucoup plus puissant et compliqué que cela, comme le disent MattBianco et Nir. Bien que la deuxième partie de la réponse soit très bonne. C'est vrai ce que Blivet a dit, et c'est un bon conseil.
santiagobasulto
10
Aussi 1 note importante, DATETIME et TIMESTAMP peuvent utiliser CURRENT_TIMESTAMP, NOW () avec respect car c'est la valeur par défaut, mais DATE par exemple ne peut pas, car il utilise '0000-00-00' par défaut, donc pour résoudre ce problème, U devrait écrire Votre propre déclencheur à cette table, pour insérer la date actuelle (sans heure) dans le champ / col avec le type DATE mysql.
Arthur Kushman
14
@DavidHarkness: La documentation indique "Pour spécifier des propriétés automatiques, utilisez les clauses DEFAULT CURRENT_TIMESTAMP et ON UPDATE CURRENT_TIMESTAMP" dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
Plap
916

Dans MySQL 5 et versions ultérieures, les valeurs TIMESTAMP sont converties du fuseau horaire actuel en UTC pour le stockage, et reconverties de l'UTC au fuseau horaire actuel pour la récupération. (Cela se produit uniquement pour le type de données TIMESTAMP et non pour d'autres types tels que DATETIME.)

Par défaut, le fuseau horaire actuel pour chaque connexion est l'heure du serveur. Le fuseau horaire peut être défini pour chaque connexion, comme décrit dans Prise en charge du fuseau horaire du serveur MySQL .

Nir
la source
11
cette présentation OReilly est très bonne pour ce sujet (PDF désolé) cdn.oreillystatic.com/en/assets/1/event/36/…
gcb
13
Il s'agit également de la nature de l'événement: - Une vidéoconférence (TIMESTAMP). Tous les participants devraient voir une référence à un instant absolu de temps ajusté à son fuseau horaire. - Une heure locale (DATETIME), je devrais faire cette tâche au 31/03/2014 à 9h00, peu importe si ce jour-là je travaille à New York ou Paris. Je vais commencer à travailler à 8 h 00, heure locale, je serai ce jour-là.
yucer
1
Donc, si je CHANGE le fuseau horaire du serveur, la valeur de TIMESTAMP restera la même ou changera-t-elle aussi ??
Andrew
3
@Andrew puisque c'est UTC, il restera UTC. Cependant, la conversion en arrière passera au "nouveau" fuseau horaire du serveur.
nembleton
@yucer - Je ne recommande pas de penser de cette façon. L'utilisation la plus cohérente dans une économie mondiale consiste à convertir toutes les heures de données en UTC pour le stockage. Par convention, traitez Datetime comme un champ UTC. Cela impose un fardeau à toutes les tâches qui saisissent des heures pour effectuer la conversion en UTC, mais c'est une conception plus propre à long terme. Bien sûr, présentez les informations à l'utilisateur en fonction de ses paramètres actuels. Si l'utilisateur souhaite entrer "09h00 à Paris", laissez-le régler l'heure de Paris, puis entrez 09h00. Ensuite, toute personne qui se trouve à New York peut facilement trouver l'heure à laquelle elle doit être éveillée à son heure, pour une téléconférence.
ToolmakerSteve
524

J'utilise toujours les champs DATETIME pour autre chose que des métadonnées de ligne (date de création ou de modification).

Comme mentionné dans la documentation MySQL:

Le type DATETIME est utilisé lorsque vous avez besoin de valeurs contenant à la fois des informations de date et d'heure. MySQL récupère et affiche les valeurs DATETIME au format 'YYYY-MM-DD HH: MM: SS'. La plage prise en charge est de '1000-01-01 00:00:00' à '9999-12-31 23:59:59'.

...

Le type de données TIMESTAMP a une plage de '1970-01-01 00:00:01' UTC à '2038-01-09 03:14:07' UTC. Il a des propriétés variables, selon la version de MySQL et le mode SQL dans lequel le serveur s'exécute.

Il est fort probable que vous atteigniez la limite inférieure des TIMESTAMPs en général - par exemple, le stockage de la date de naissance.

scronide
la source
195
vous pouvez également atteindre facilement la limite supérieure si vous travaillez dans le secteur bancaire ou immobilier ... Les prêts hypothécaires à 30 ans vont maintenant au-delà de 2038
Kip
16
Bien sûr, utilisez des horodatages Unix 64 bits. Par exemple, en Java, new Date().getTime()vous donne déjà une valeur 64 bits.
osa
5
+1 pour DATETIME: dans notre flux de données, depuis SQL Server du magasin physique pour achat et facture, transféré vers MySQL Server pour le magasin virtuel sur la page Web, DATETIME est préférable pour la modification date-heure car ce type de données existe également dans Transact -SQL. Mais TIMESTAMP signifie autre chose dans Transact-SQL, il est binaire comme ROWVERSION, bien que MySQL TIMESTAMP soit similaire à DateTime. Nous évitons donc l'utilisation de TIMESTAMP pour la compatibilité des deux bases de données.
jacouh
10
Aucune idée. C'est un problème beaucoup plus important que juste MySQL et il n'y a pas de solution simple: en.wikipedia.org/wiki/Year_2038_problem Je ne crois pas que MySQL puisse simplement déclarer que les horodatages sont maintenant 64 bits et supposer que tout ira bien. Ils ne contrôlent pas le matériel.
scronide
5
Une date de naissance peut être une DATETIME si vous connaissez l'heure de naissance, comme moi pour la mienne.
Kris Craig
322

Les exemples ci-dessous montrent comment le TIMESTAMPtype de date a changé les valeurs après avoir changé time-zone to 'america/new_york'DATETIMEest inchangé.

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

J'ai converti ma réponse en article afin que plus de gens puissent trouver cela utile, MySQL: Datetime Versus Timestamp Data Types .

mr_eclair
la source
55
Eh bien, en fait, le DATETIMEtemps effectif a changé avec le changement de fuseau horaire, TIMESTAMPn'a pas changé, mais la représentation humaine a changé.
flindeberg
3
Il semble que cette commande ne fonctionne pas dans MySQL 5.6 set time_zone="america/new_york";
Manjunath Reddy
Voici la réponse au problème de set time_zone. stackoverflow.com/questions/3451847/mysql-timezone-change
Manjunath Reddy
2
D'accord avec @flindeberg. L'horodatage représente l'heure correcte, et non l'heure, après le changement de fuseau horaire
Nitin Bansal
193

La principale différence est que DATETIME est constant tandis que TIMESTAMP est affecté par le time_zoneparamètre.

Cela n'a donc d'importance que lorsque vous avez - ou pourriez avoir à l'avenir - des clusters synchronisés sur plusieurs fuseaux horaires.

En termes plus simples: si j'ai une base de données en Australie et que je fais un vidage de cette base de données pour synchroniser / remplir une base de données en Amérique, le TIMESTAMP serait mis à jour pour refléter l'heure réelle de l'événement dans le nouveau fuseau horaire, tandis que DATETIME reflètent toujours l'heure de l'événement dans le fuseau horaire de l'UA .

Un excellent exemple d'utilisation de DATETIME là où TIMESTAMP aurait dû être utilisé est sur Facebook, où leurs serveurs ne sont jamais tout à fait sûrs de ce qui s'est passé entre les fuseaux horaires. Une fois, j'ai eu une conversation dans laquelle le temps a dit que je répondais aux messages avant que le message ne soit envoyé. (Bien sûr, cela pourrait également être dû à une mauvaise traduction du fuseau horaire dans le logiciel de messagerie si les heures étaient affichées plutôt que synchronisées.)

ekerner
la source
83
Je ne pense pas que ce soit une bonne façon de penser. Je voudrais simplement stocker et traiter toutes les dates en UTC et m'assurer que le front-end l'affiche en fonction du fuseau horaire donné. Cette approche est simple et prévisible.
Kos
8
@Kos: le stockage et le traitement de toutes les dates en UTC ne sont-ils pas exactement ce que TIMESTAMP fait en interne? (Puis le convertir pour afficher votre fuseau horaire local?)
carbocation
10
mon fuseau horaire local? Comment votre base de données connaîtrait-elle mon fuseau horaire? ;-) Il y a normalement pas mal de traitement entre la base de données et l'interface utilisateur. Je ne fais la localisation qu'après tout le traitement.
Kos
3
@Koz: ma base de données ne connaît pas le fuseau horaire de votre base de données:! Mais il connaît l'horodatage. Votre base de données connaît son propre paramètre de fuseau horaire et l'applique lors de l'interprétation / de la représentation de l'horodatage. 01h01 le 11 décembre 2013 à Pékin La Chine n'est pas le même moment que 01h01 le 11 décembre 2013 à Sydney en Australie. Google: «fuseaux horaires» et «premier méridien».
ekerner
2
MySQL convertit les valeurs TIMESTAMP du fuseau horaire actuel en UTC pour le stockage, et de retour de l'UTC vers le fuseau horaire actuel pour la récupération. (Cela ne se produit pas pour d'autres types tels que DATETIME.) Dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo
125

Je prends cette décision sur une base sémantique.

J'utilise un horodatage lorsque j'ai besoin d'enregistrer un point fixe (plus ou moins) dans le temps. Par exemple, lorsqu'un enregistrement a été inséré dans la base de données ou lorsqu'une action utilisateur a eu lieu.

J'utilise un champ datetime lorsque la date / heure peut être définie et modifiée arbitrairement. Par exemple, lorsqu'un utilisateur peut enregistrer des rendez-vous de modification ultérieurs.

MaxVT
la source
horodatage - point fixe dans le temps, temps universel coordonné datetime - par rapport à un point de vue, à une référence temporelle (heure locale du fuseau horaire ej), pourrait être .. Heure locale coordonnée?
yucer
110

Je recommande d'utiliser ni un champ DATETIME ou TIMESTAMP. Si vous souhaitez représenter un jour spécifique dans son ensemble (comme un anniversaire), utilisez un type DATE, mais si vous êtes plus précis que cela, vous êtes probablement intéressé à enregistrer un moment réel par opposition à une unité de heure (jour, semaine, mois, année). Au lieu d'utiliser un DATETIME ou TIMESTAMP, utilisez un BIGINT et stockez simplement le nombre de millisecondes depuis l'époque (System.currentTimeMillis () si vous utilisez Java). Cela présente plusieurs avantages:

  1. Vous évitez le blocage des fournisseurs. Presque toutes les bases de données prennent en charge des entiers de manière relativement similaire. Supposons que vous souhaitiez passer à une autre base de données. Voulez-vous vous soucier des différences entre les valeurs DATETIME de MySQL et comment Oracle les définit? Même parmi différentes versions de MySQL, TIMESTAMPS ont un niveau de précision différent. Ce n'est que récemment que MySQL a pris en charge les millisecondes dans les horodatages.
  2. Aucun problème de fuseau horaire. Il y a eu quelques commentaires perspicaces sur ce qui se passe avec les fuseaux horaires avec les différents types de données. Mais est-ce une connaissance commune, et vos collègues prendront-ils tous le temps de l'apprendre? D'un autre côté, il est assez difficile de gâcher la transformation d'un BigINT en java.util.Date. L'utilisation d'un BIGINT provoque la chute de nombreux problèmes avec les fuseaux horaires.
  3. Aucun souci de portée ou de précision. Vous n'avez pas à vous soucier de ce qui sera écourté par les futures plages de dates (TIMESTAMP ne va qu'en 2038).
  4. Intégration d'outils tiers. En utilisant un entier, il est trivial pour les outils tiers (par exemple EclipseLink) de s'interfacer avec la base de données. Tous les outils tiers n'auront pas la même compréhension d'une «date / heure» que MySQL. Vous voulez essayer de déterminer dans Hibernate si vous devez utiliser un objet java.sql.TimeStamp ou java.util.Date si vous utilisez ces types de données personnalisés? L'utilisation de vos types de données de base est facile à utiliser avec des outils tiers.

Ce problème est étroitement lié à la façon dont vous devez stocker une valeur monétaire (c'est-à-dire 1,99 $) dans une base de données. Devez-vous utiliser un Decimal, ou le type Money de la base de données, ou pire encore un Double? Ces 3 options sont terribles, pour plusieurs des mêmes raisons énumérées ci-dessus. La solution consiste à stocker la valeur de l'argent en cents à l'aide de BIGINT, puis à convertir les cents en dollars lorsque vous affichez la valeur à l'utilisateur. Le travail de la base de données consiste à stocker des données et NON à interpréter ces données. Tous ces types de données sophistiqués que vous voyez dans les bases de données (en particulier Oracle) ajoutent peu et vous lancent sur la voie du verrouillage des fournisseurs.

user64141
la source
12
J'aime cette solution. TIMESTAMP expirant en 2038 est un problème majeur. Ce n'est pas si loin!
Charlie Dalsass
4
@CharlieDalsass Pensez-vous que le logiciel actuel sera là à cette époque :-P
Habeeb Perwad
13
Il est difficile d'interroger les données par date si elles sont stockées sous forme de nombre de millisecondes
Ali Saeed
4
C'est vraiment la meilleure solution si vous vous souciez de la portabilité et de la gestion des utilisateurs dans plusieurs fuseaux horaires, ou de la base de données dans un fuseau horaire différent de celui des utilisateurs. TIMESTAMP pourrait être la voie à suivre s'il n'a pas de défauts de conception. Dommage que les solutions cassées aient obtenu plus de votes car elles ont été publiées tôt (des années!).
Allemand
4
Excellente solution! Et vous avez parfaitement raison d'être "enfermé". Lorsque vous prenez l'habitude de laisser les autres "faire le travail pour vous", alors vous commencez à perdre les morceaux qui font de VOUS le programmeur.
fmc
98

TIMESTAMP est de 4 octets contre 8 octets pour DATETIME.

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

Mais comme le dit scronide, il a une limite inférieure de l'année 1970. C'est bien pour tout ce qui pourrait arriver à l'avenir;)

Alex
la source
186
L'avenir se termine à 2038-01-19 03:14:07 UTC.
MattBianco
5
C'est stupide. Je pensais que le type TIMESTAMP serait "prêt pour l'avenir" car il est relativement nouveau. Vous ne pouvez pas déranger la conversion de datetime en UTC et vice versa à chaque fois que vous travaillez avec différents fuseaux horaires. Ils auraient dû agrandir TIMESTAMP .. d'au moins 1 octet de plus. cela ajoutera 68 * 255 = 17340 années supplémentaires ... bien qu'il ne soit pas aligné sur 32 bits.
NickSoft
10
Savez-vous pourquoi TIMESTAMP se termine en 2038? Parce que c'est un entier, et les entiers ont une limite qui est 2147483647. Je pense que c'est la raison. Peut-être que s'ils changent son type en varchar et changent la façon de le manipuler, il sera "prêt pour l'avenir".
vinsa
6
@vinsa, je ne pense pas que ce sera prêt pour l'avenir. Vous vous souvenez toujours du bug Y2K? 2038 arrive.
Pacerier
2
D'ici 2038, MySQL (s'il existe toujours) mettra simplement à jour le champ TIMESTAMP pour utiliser plus de 4 octets et permettre une plage plus large
the_nuts
95
  1. TIMESTAMP est de quatre octets contre huit octets pour DATETIME.

  2. Les horodatages sont également plus légers sur la base de données et indexés plus rapidement.

  3. Le type DATETIME est utilisé lorsque vous avez besoin de valeurs contenant à la fois des informations de date et d'heure. MySQL récupère et affiche les valeurs DATETIME au format 'YYYY-MM-DD HH: MM: SS'. La plage prise en charge est de '1000-01-01 00:00:00' à '9999-12-31 23:59:59'.

Le type de données TIMESTAMP a une plage de '1970-01-01 00:00:01' UTC à '2038-01-09 03:14:07' UTC. Il a des propriétés variables, selon la version de MySQL et le mode SQL dans lequel le serveur s'exécute.

  1. DATETIME est constant tandis que TIMESTAMP est affecté par le paramètre time_zone.
Vivek S
la source
6
Vous devez clarifier # 4: l'horodatage tel qu'il est stocké est constant et non relatif (complètement agnostique) au fuseau horaire, tandis que la sortie affichée lors de la récupération est affectée par le fuseau horaire de la session demandeuse. DATETIME est toujours relatif au fuseau horaire dans lequel il a été enregistré et doit toujours être considéré dans ce contexte, une responsabilité qui incombe désormais à l'application.
Christopher McGowan
1
Très bonne réponse. Pour ajouter à cette réponse, si nous essayons de stocker des valeurs au-delà de '2038-01-09 03:14:07', nous obtenons soit une erreur, soit elle est stockée en tant que '0000-00-00 00:00:00'. J'obtenais cette erreur pour ma base de données car elle a des valeurs décalées dans le temps (à des fins de chiffrement).
KarthikS
De plus, il y a un problème avec DATETIME avec la valeur DEFAULT sur les versions de mysql inférieures à 5.5. dba.stackexchange.com/questions/132951/…
Velaro
47

Cela dépend de l'application, vraiment.

Pensez à définir un horodatage par un utilisateur sur un serveur à New York, pour un rendez-vous à Sanghai. Désormais, lorsque l'utilisateur se connecte à Sanghai, il accède au même horodatage de rendez-vous à partir d'un serveur en miroir à Tokyo. Il verra le rendez-vous à l'heure de Tokyo, décalé de l'heure d'origine de New York.

Ainsi, pour les valeurs qui représentent le temps de l'utilisateur comme un rendez-vous ou un horaire, datetime est meilleur. Il permet à l'utilisateur de contrôler la date et l'heure exactes souhaitées, quels que soient les paramètres du serveur. L'heure définie est l'heure définie, non affectée par le fuseau horaire du serveur, le fuseau horaire de l'utilisateur ou par les changements dans la façon dont l'heure d'été est calculée (oui, elle change).

D'un autre côté, pour les valeurs qui représentent l'heure système comme les transactions de paiement, les modifications de table ou la journalisation, utilisez toujours des horodatages. Le système ne sera pas affecté par le déplacement du serveur vers un autre fuseau horaire ou lors de la comparaison entre des serveurs dans des fuseaux horaires différents.

Les horodatages sont également plus légers sur la base de données et indexés plus rapidement.

ianaré
la source
Votre application ne doit pas s'appuyer sur le fuseau horaire du serveur. Une application doit TOUJOURS sélectionner le fuseau horaire dans la session de la connexion à la base de données qu'elle utilise avant d'émettre une requête. Si une connexion est partagée entre plusieurs utilisateurs (ex: webapp), utilisez UTC et effectuez une conversion de fuseau horaire du côté du rendu.
dolmen
42

2016 + : ce que je conseille, c'est de régler votre fuseau horaire Mysql sur UTC et d'utiliser DATETIME:

Tout framework frontal récent (Angular 1/2, react, Vue, ...) peut facilement et automatiquement convertir votre datetime UTC en heure locale.

Aditionellement:

(Sauf si vous êtes susceptible de modifier le fuseau horaire de vos serveurs)


Exemple avec 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' }}

Tous les formats d'heure localisés sont disponibles ici: https://docs.angularjs.org/api/ng/filter/date

Sébastien Horin
la source
8
Vos données ne doivent pas être attachées aux paramètres de fuseau horaire de vos serveurs. Peut-être que cela fonctionne pour vous si vous avez une seule boîte MySql sous votre bureau
Jin
@Jin UTC signifie aucun fuseau horaire comme TIMESTAMP. Si tous vos serveurs sont en UTC, il n'y a aucun problème. Peut-être que cela ne fonctionne pas pour vous si vous avez une configuration des années 2000.
Sebastien Horin
TIMESTAMP peut être mis à niveau vers une valeur 64 bits à l'avenir. Ensuite, il n'y a plus de problème.
2017
Charger des bibliothèques tierces entières pour attraper quelque chose comme ça ne peut pas non plus être génial pour les performances, n'est-ce pas? Étant donné que c'est côté client et n'affecte pas votre base de données ... Quoi qu'il en soit, tout ce que vous faites en front-end nécessitera des vérifications côté serveur. Donc, en pensant à l' image complète , cela aide-t-il vraiment avec le problème de vitesse? - Ces repères sont un peu étranges d'ailleurs, je pense. L'utilisation d'une chaîne dans une requête pour comparer des champs d'horodatage semble également assez étrange. Cela doit également nuire aux performances, non?
NoobishPro
1
Ne comptez pas dans votre application sur la zone horaire du serveur. Définissez plutôt la zone horaire à utiliser sur chaque connexion à la base de données: SET time_zone = '+0:00';pour UTC.
dolmen
37

Un timestampchamp est un cas particulier du datetimechamp. Vous pouvez créertimestamp colonnes pour avoir des propriétés spéciales; il peut être configuré pour se mettre à jour lors de la création et / ou de la mise à jour.

En termes de base de données "plus grande", timestamp contient quelques déclencheurs de cas spéciaux.

Le bon choix dépend entièrement de ce que vous voulez faire.

Jeff Warnica
la source
6
Non, la différence n'est pas seulement "un cas spécial". Parce que les fuseaux horaires de la session qui définit / interroge les valeurs sont impliqués différemment.
dolmen
Je suis content que vous ayez mis "ce qui est juste dépend entièrement de ce que vous voulez faire." Il y a trop de réponses sur SE qui disent, sans justification suffisante, "Vous ne devez jamais faire X" ou "Vous devez toujours faire Y".
Agi Hammerthief
37

TIMESTAMP est toujours en UTC (c'est-à-dire en secondes écoulées depuis le 01/01/1970, en UTC), et votre serveur MySQL le convertit automatiquement en date / heure pour le fuseau horaire de connexion. À long terme, TIMESTAMP est la voie à suivre car vous savez que vos données temporelles seront toujours en UTC. Par exemple, vous ne bousillerez pas vos dates si vous migrez vers un autre serveur ou si vous modifiez les paramètres de fuseau horaire sur votre serveur.

Remarque: le fuseau horaire de connexion par défaut est le fuseau horaire du serveur, mais il peut (devrait) être modifié par session (voir SET time_zone = ...).

Sobes
la source
29

Comparaison entre DATETIME, TIMESTAMP et DATE

entrez la description de l'image ici

Quelle est cette [.fraction]?

  • Une valeur DATETIME ou TIMESTAMP peut inclure une partie de fraction de seconde de fin avec une précision allant jusqu'à quelques microsecondes (6 chiffres). En particulier, toute partie fractionnaire d'une valeur insérée dans une colonne DATETIME ou TIMESTAMP est stockée plutôt que supprimée. C'est bien sûr facultatif.

Sources:

Dehan de Croos
la source
24

J'utiliserais toujours un horodatage Unix pour travailler avec MySQL et PHP. La raison principale en est la date par défaut méthode de en PHP utilise un horodatage comme paramètre, donc aucune analyse syntaxique n'est nécessaire.

Pour obtenir l'horodatage Unix actuel en PHP, faites-le time();
et faites -le dans MySQL SELECT UNIX_TIMESTAMP();.

Mark Davidson
la source
6
-1 Je pense en fait que la réponse ci-dessous est meilleure - l'utilisation de datetime vous permet de pousser plus de logique pour le traitement des dates dans MySQL lui-même, ce qui peut être très utile.
Toby Hede
N'y a-t-il pas eu des benchmarks montrant que le tri dans MySQL est plus lent qu'en php?
sdkfasldf
ça dépend, parfois c'est bien de l'utiliser quand on aime ne pas utiliser strtotime. (php5.3 dep)
Adam Ramadhan
vous pouvez pousser la logique dans mysql en utilisant simplement FROM_UNIXTIME si nécessaire
inarilo
J'utilisais tous les horodatages Unix dans mes applications PHP et dans MySQL, mais j'ai trouvé qu'il était beaucoup plus pratique de stocker les dates et heures dans MySQL en tant que types de date / heure natifs. Ceci est particulièrement utile à des fins de génération de rapports et uniquement pour parcourir les ensembles de données. Au fil du temps, frustré de devoir copier / coller les horodatages Unix, j'ai commencé à changer. Je suis tout à fait certain qu'il existe des performances et d'autres avantages / inconvénients, mais en fonction de votre cas d'utilisation, la commodité peut être plus importante que les micro-optimisations.
DavidScherer
24

Il convient de noter que dans MySQL, vous pouvez utiliser quelque chose dans le sens ci-dessous lors de la création de vos colonnes de table:

on update CURRENT_TIMESTAMP

Cela mettra à jour l'heure à laquelle vous modifiez une ligne à chaque instance et est parfois très utile pour les informations de dernière modification stockées. Cela ne fonctionne qu'avec horodatage, pas datetime cependant.

leejmurphy
la source
17

D'après mon expérience, si vous voulez un champ de date dans lequel l'insertion ne se produit qu'une seule fois et que vous ne voulez pas avoir de mise à jour ou toute autre action sur ce champ particulier, choisissez la date et l'heure .

Par exemple, considérons une usertable avec un champ DATE D'ENREGISTREMENT . Dans ce usertableau, si vous souhaitez connaître la dernière heure de connexion d'un utilisateur particulier, utilisez un champ de type horodatage pour que le champ soit mis à jour.

Si vous créez la table à partir de phpMyAdmin, le paramètre par défaut mettra à jour le champ d' horodatage lorsqu'une mise à jour de ligne se produit. Si votre horodatage déposé ne se met pas à jour avec la mise à jour des lignes, vous pouvez utiliser la requête suivante pour que le champ d' horodatage soit automatiquement mis à jour.

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Kannan Prasad
la source
15

Le type de données d'horodatage stocke la date et l'heure, mais au format UTC, pas au format de fuseau horaire actuel comme le fait datetime. Et lorsque vous récupérez des données, l'horodatage les convertit à nouveau dans le fuseau horaire actuel.

Supposons donc que vous vous trouviez aux États-Unis et que vous obteniez des données d'un serveur dont le fuseau horaire est celui des États-Unis. Ensuite, vous obtiendrez la date et l'heure en fonction du fuseau horaire des États-Unis. La colonne de type de données d'horodatage est toujours mise à jour automatiquement lorsque sa ligne est mise à jour. Il peut donc être utile de suivre quand une ligne particulière a été mise à jour la dernière fois.

Pour plus de détails, vous pouvez lire l'article de blog Timestamp Vs Datetime .

Arvind
la source
Vous pouvez (devez) toujours définir le fuseau horaire au niveau de la session avec SET time_zone = '+0:00';(UTC ici) pour être sûr de ce que vous obtenez / définissez à partir des TIMESTAMPvaleurs et éviter de dépendre du serveur time_zone par défaut qui pourrait changer.
dolmen
14

J'utilise toujours un horodatage Unix, simplement pour maintenir la raison lorsque je traite de nombreuses informations datetime, en particulier lors de l'ajustement des fuseaux horaires, de l'ajout / de la soustraction de dates, etc. Lorsque vous comparez des horodatages, cela exclut les facteurs de complication du fuseau horaire et vous permet d'économiser des ressources dans votre traitement côté serveur (que ce soit le code d'application ou les requêtes de base de données) en ce que vous utilisez l'arithmétique légère plutôt que d'ajouter / soustraire une date / heure plus lourde. les fonctions.

Une autre chose à considérer:

Si vous créez une application, vous ne savez jamais comment vos données peuvent être utilisées sur toute la ligne. Si vous devez comparer, par exemple, un ensemble d'enregistrements dans votre ensemble de données avec, par exemple, un ensemble d'éléments d'une API tierce, et dire, les mettre dans l'ordre chronologique, vous serez heureux d'avoir Horodatages Unix pour vos lignes. Même si vous décidez d'utiliser les horodatages MySQL, stockez un horodatage Unix comme assurance.

Oliver Holmberg
la source
14

Dans mon cas, j'ai défini UTC comme fuseau horaire pour tout: le système, le serveur de base de données, etc. chaque fois que je le peux. Si mon client a besoin d'un autre fuseau horaire, je le configure sur l'application.

Je préfère presque toujours les horodatages plutôt que les champs datetime, car les horodatages incluent implicitement le fuseau horaire. Donc, depuis le moment où l'application sera accessible à partir d'utilisateurs de différents fuseaux horaires et que vous souhaitez qu'ils voient les dates et les heures dans leur fuseau horaire local, ce type de champ le rend assez facile à faire que si les données étaient enregistrées dans des champs datetime .

En plus, dans le cas d'une migration de la base de données vers un système avec un autre fuseau horaire, je me sentirais plus en confiance en utilisant des horodatages. Pour ne pas dire les problèmes possibles lors du calcul des différences entre deux moments avec un changement d'heure entre les deux et nécessitant une précision de 1 heure ou moins.

Donc, pour résumer, j'apprécie les avantages de l'horodatage:

  • prêt à l'emploi sur les applications internationales (multi fuseau horaire)
  • migrations faciles entre les fuseaux horaires
  • assez facile à calculer les différences (il suffit de soustraire les deux horodatages)
  • ne vous inquiétez pas des dates d'entrée / sortie d'une période d'été

Pour toutes ces raisons, je choisis les champs UTC et d'horodatage lorsque cela est possible. Et j'évite les maux de tête;)

Roger Campanera
la source
les données d'horodatage seront amusantes pour la personne qui prend en charge votre demande lorsque le 20 janvier 2038 arrivera. tick tock tick tock
Wilson Hauck
Le type d'horodatage pourrait alors être augmenté d'un peu et doubler les valeurs possibles.
Roger Campanera
Testez votre théorie pour 'augmenter un peu' et voyez si vous pouvez stocker avec succès le 1er février 2038 et la récupérer avec MySQL. Voyons la définition de votre table une fois terminé, s'il vous plaît. Vous allez probablement avoir beaucoup de connaissances passées malheureuses en février 2038.
Wilson Hauck
1
@WilsonHauck Vous devrez de toute façon mettre à jour la version MySQL bien avant 2038. Et ce TIMESTAMP étendu sera géré par la migration. En outre, peu d'applications en plus de la gestion des hypothèques doivent vraiment se préoccuper de 2038 en ce moment.
dolmen
@dolmen de nombreux outils et matériaux de qualité professionnelle ont une garantie de plus de 20 ans. Donc, quelque chose comme ça warranties.expires_atne pouvait pas être un horodatage MySQL aujourd'hui.
alexw
13

Méfiez-vous des modifications d'horodatage lorsque vous effectuez une instruction UPDATE sur une table. Si vous avez une table avec des colonnes 'Name' (varchar), 'Age' (int) et 'Date_Added' (horodatage) et que vous exécutez l'instruction DML suivante

UPDATE table
SET age = 30

puis chaque valeur unique dans votre colonne "Date_Added" serait remplacée par l'horodatage actuel.

Lloyd Banks
la source
3
en fonction de la configuration de votre table, vous pouvez contrôler ce comportement. regardez dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Charles Faiga
5
@CharlesFaiga Le comportement par défaut est que l'horodatage soit mis à jour lorsqu'une autre colonne est mise à jour. Vous devez explicitement désactiver cette option si vous souhaitez que l'horodatage conserve sa valeur d'origine
Lloyd Banks
Qu'est-ce que c'est ?! vous devez définir la colonne d'horodatage surON UPDATE CURRENT_TIMESTAMP
Accountant م
Il s'agit d'une fonctionnalité que vous devez activer explicitement lors de la création de la table.
dolmen
13

Référence tirée de cet article:

Les principales différences:

TIMESTAMP permet de suivre les modifications apportées aux enregistrements et de les mettre à jour chaque fois que l'enregistrement est modifié. DATETIME utilisé pour stocker une valeur spécifique et statique qui n'est affectée par aucun changement dans les enregistrements.

TIMESTAMP est également affecté par différents paramètres liés à TIME ZONE. DATETIME est constant.

TIMESTAMP a converti en interne le fuseau horaire actuel en UTC pour le stockage et, pendant la récupération, reconverti dans le fuseau horaire actuel. DATETIME ne peut pas faire cela.

Plage prise en charge par TIMESTAMP: '1970-01-01 00:00:01 ′ UTC à' 2038-01-19 03:14:07 'UTC DATETIME plage prise en charge:' 1000-01-01 00:00:00 ′ à '9999 -12-31 23:59:59 ′

Anvesh
la source
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
la source
10

Une autre différence entre l'horodatage et la date et l'heure réside dans l'horodatage dont la valeur par défaut est NULL.

ecleel
la source
8
C'est évidemment faux. Voici un exemple: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); La première colonne peut accepter une valeur NULL.
Ormoz
10

J'ai trouvé une utilité inégalée dans la capacité de TIMESTAMP à se mettre à jour automatiquement en fonction de l'heure actuelle sans utiliser de déclencheurs inutiles. C'est juste moi cependant, bien que TIMESTAMP soit UTC comme il a été dit.

Il peut garder une trace sur différents fuseaux horaires, donc si vous devez afficher une heure relative par exemple, l'heure UTC est ce que vous souhaitez.

Marc DiMillo
la source
9

La principale différence est

regardez ce post pour voir les problèmes d'indexation Datetime

Charles Faiga
la source
6
Les deux ont le même problème si vous sélectionnez avec une fonction basée sur la valeur de la colonne, et les deux peuvent être indexés.
Marcus Adams
4
L'index fonctionne sur l'horodatage et ne fonctionne pas sur datetime? Vous avez tiré des conclusions erronées de ces messages.
Salman A
9

J'ai cessé d'utiliser datetimedans mes applications après avoir rencontré de nombreux problèmes et bugs liés aux fuseaux horaires. À mon humble avis, l'utilisation timestampest meilleure que datetimedans la plupart des cas .

Quand vous demandez quel est le temps? et la réponse vient comme quelque chose comme '2019-02-05 21:18:30', qui n'est pas terminée, pas de réponse définie car il manque une autre partie, dans quel fuseau horaire? Washington? Moscou? Pékin ?

L'utilisation d'heures sans le fuseau horaire signifie que votre application ne traite que d'un seul fuseau horaire, mais les horodatages vous offrent les avantages datetimeet la flexibilité d'afficher le même moment exact dans différents fuseaux horaires.

Voici quelques cas qui vous feront regretter d'utiliser datetimeet souhaiteront avoir stocké vos données dans des horodatages.

  1. Pour le confort de vos clients, vous voulez leur montrer les heures en fonction de leurs fuseaux horaires préférés sans les obliger à faire le calcul et convertir l'heure en leur fuseau horaire significatif. tout ce dont vous avez besoin est de changer le fuseau horaire et tout votre code d'application sera le même. (En fait, vous devez toujours définir le fuseau horaire au début de l'application, ou demander un traitement dans le cas d'applications PHP)

    SET time_zone = '+2:00';
  2. vous avez changé le pays dans lequel vous séjournez et poursuivez votre travail de maintenance des données tout en les visualisant dans un fuseau horaire différent (sans modifier les données réelles).

  3. vous acceptez les données de différents clients du monde entier, chacun insère l'heure dans son fuseau horaire.

En bref

datetime = l'application prend en charge 1 fuseau horaire (pour l'insertion et la sélection)

timestamp = l'application prend en charge n'importe quel fuseau horaire (pour l'insertion et la sélection)


Cette réponse est uniquement pour mettre en évidence la flexibilité et la facilité des horodatages en ce qui concerne les fuseaux horaires, elle ne couvre pas d'autres différences telles que la taille ou la plage de colonnes ou la fraction .

Comptable م
la source
que faire s'il y a des champs qui utilisent dateet d'autres champs utilisent timestampdans une table. Je pense que cela causera un nouveau problème car les données filtrées wherene sont pas conformes aux changements de fuseau horaire.
Erlang P
@ErlangP Dans ce cas, votre application doit résoudre le problème de fuseau horaire sur la datecolonne avant d'envoyer la requête.
Accountant م
7

Je préfère utiliser l'horodatage afin de tout garder dans un format brut commun et de formater les données en code PHP ou dans votre requête SQL. Il y a des cas où il est utile dans votre code pour tout garder en quelques secondes.

Hans
la source
7

A TIMESTAMPnécessite 4 octets, tandis que a DATETIMErequiert 8 octets.

Mwangi Thiga
la source
6

J'aime un horodatage Unix, car vous pouvez convertir en nombres et vous soucier du nombre. De plus, vous ajoutez / soustrayez et obtenez des durées, etc. Convertissez ensuite le résultat en Date dans n'importe quel format. Ce code découvre combien de temps en minutes s'est écoulé entre un horodatage d'un document et l'heure actuelle.

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);
user723220
la source
4
Ou, utilisez un datetime MySQL lisible et natif, et utilisez des fonctions MySQL natives pour ajouter / soustraire des datetimes.
Julien Palard