Mysql
 sql >> Base de données >  >> RDS >> Mysql

Longueur DECIMALE pour microtime(true) ?

tl;dr. Utilisez microtime(false) et stockez les résultats dans un bigint MySQL en millionièmes de secondes. Sinon, vous devez tout apprendre sur l'arithmétique en virgule flottante, qui est une grosse boule de poils.

La fonction PHP microtime récupère l'horodatage Unix (actuellement environ 50eb7c00 hexadécimal ou 1 357 609 984 décimal) d'un appel système et l'heure en microsecondes d'un autre appel système. Il les transforme ensuite en une chaîne de caractères. Ensuite, si vous l'appelez avec (true), il convertit ce nombre en un nombre à virgule flottante IEEE 745 64 bits, une chose que PHP appelle un float .

À partir d'aujourd'hui, vous avez besoin de dix chiffres décimaux à gauche de la virgule pour stocker un horodatage UNIX entier. Cela restera vrai jusqu'à environ 2280 EC lorsque vos descendants commenceront à avoir besoin de onze chiffres. Vous aurez besoin de six chiffres à droite de la décimale pour stocker les microsecondes.

Vous n'obtiendrez pas une précision totale à la microseconde. La plupart des systèmes conservent leur horloge système inférieure à la seconde avec une résolution de quelque chose dans la plage de 1 à 33 millisecondes. Cela dépend du système.

MySQL version 5.6.4 et ultérieure vous permet de spécifier DATETIME(6) colonnes, qui contiendront les dates et les heures à la résolution de la microseconde. Si vous utilisez une telle version de MySQL, c'est absolument la voie à suivre.

Avant la version 5.6.4, vous devez utiliser MySQL DOUBLE (virgule flottante IEEE 754 64 bits) pour stocker ces nombres. MySQL FLOAT (virgule flottante 32 bits IEEE 754) n'a pas assez de bits dans sa mantisse pour stocker même l'heure UNIX actuelle en secondes de manière complètement précise.

Pourquoi stockez-vous ces horodatages ? Espérez-vous faire

  WHERE table.timestamp = 1357609984.100000

ou des requêtes similaires pour rechercher des éléments particuliers ? C'est très périlleux si vous utilisez des nombres flottants ou doubles n'importe où dans votre chaîne de traitement (c'est-à-dire, même si vous utilisez microtime(true) même une fois). Ils sont connus pour ne pas être égaux même lorsque vous pensiez qu'ils le devraient. Au lieu de cela, vous devez utiliser quelque chose comme ça. Le 0.001 ì s'appelle "epsilon" dans le métier du traitement numérique.

  WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
                            AND 1357609984.100000 + 0.001

ou quelque chose de similaire. Vous n'aurez pas ce problème si vous stockez ces horodatages sous forme de décimales ou en millionièmes de secondes dans un bigint colonne.

La virgule flottante IEEE 64 bits a 53 bits de mantisse -- de précision. L'horodatage UNIX Epoch actuel (secondes depuis le 1er janvier 1970 00:00Z) multiplié par un million utilise 51 bits. Il n'y a donc pas beaucoup de précision supplémentaire dans le DOUBLE si nous nous soucions du bit de poids faible. D'un autre côté, la précision ne s'épuisera pas avant quelques siècles.

Vous êtes loin de manquer de précision avec int64(BIGINT). Si je stockais réellement des horodatages en microsecondes uniquement pour les commander dans MySQL, j'irais avec DATETIME(6) parce que j'obtiendrais beaucoup d'arithmétique de date gratuitement. Si je faisais une application à volume élevé en mémoire, j'utiliserais int64.