Mysql
 sql >> Datenbank >  >> RDS >> Mysql

DEZIMAL-Länge für Microtime (true)?

tl;dr. Verwenden Sie microtime(false) und speichern Sie die Ergebnisse in einem MySQL-Bigint als Millionstel Sekunden. Andernfalls müssen Sie alles über Fließkomma-Arithmetik lernen, was ein großer, fetter Haarball ist.

Die PHP-Microtime-Funktion erfasst den Unix-Zeitstempel (derzeit etwa hex 50eb7c00 oder dezimal 1.357.609.984) von einem Systemaufruf und die Mikrosekundenzeit von einem anderen Systemaufruf. Es macht sie dann zu einer Zeichenkette. Wenn Sie es dann mit (true) aufrufen, wandelt es diese Zahl in eine 64-Bit-IEEE-745-Gleitkommazahl um, eine Sache, die PHP als float bezeichnet .

Ab heute benötigt man zehn Dezimalstellen links vom Dezimalpunkt, um einen ganzzahligen UNIX-Zeitstempel zu speichern. Das wird bis etwa 2280 n. Chr. so bleiben, wenn Ihre Nachkommen elf Ziffern benötigen werden. Sie benötigen sechs Ziffern rechts von der Dezimalstelle, um die Mikrosekunden zu speichern.

Sie werden keine vollständige Mikrosekundengenauigkeit erhalten. Die meisten Systeme halten ihre Subsekunden-Systemuhr mit einer Auflösung von etwas im Bereich von 1–33 Millisekunden. Es ist systemabhängig.

Ab MySQL-Version 5.6.4 können Sie DATETIME(6) angeben Spalten, die Datums- und Zeitangaben in Mikrosekundenauflösung enthalten. Wenn Sie eine solche MySQL-Version verwenden, ist das absolut der richtige Weg.

Vor Version 5.6.4 müssen Sie MySQL DOUBLE verwenden (IEEE 754 64-Bit-Gleitkommazahl), um diese Zahlen zu speichern. MySQL FLOAT (IEEE 754 32-Bit Floating Point) hat nicht genügend Bits in seiner Mantisse, um sogar die aktuelle UNIX-Zeit in Sekunden vollständig genau zu speichern.

Warum speichern Sie diese Zeitstempel? Hoffen Sie,

zu tun?
  WHERE table.timestamp = 1357609984.100000

oder ähnliche Abfragen, um bestimmte Artikel nachzuschlagen? Das ist gefährlich, wenn Sie irgendwo in Ihrer Verarbeitungskette Float- oder Double-Zahlen verwenden (das heißt, selbst wenn Sie microtime(true) verwenden). sogar einmal). Sie sind berüchtigt dafür, dass sie nicht gleich sind, selbst wenn Sie dachten, dass sie es sollten. Stattdessen müssen Sie so etwas verwenden. Der 0.001 wird in der Zahlenverarbeitung "epsilon" genannt.

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

oder etwas ähnliches. Sie werden dieses Problem nicht haben, wenn Sie diese Zeitstempel als Dezimalzahlen oder in Millionstel Sekunden in einem bigint speichern Spalte.

IEEE 64-Bit-Gleitkomma hat 53 Bit Mantisse – Genauigkeit. Der aktuelle Zeitstempel der UNIX-Epoche (Sekunden seit dem 1. Januar 1970 00:00 Z) mal einer Million verwendet 51 Bits. Es gibt also nicht viel zusätzliche Präzision im DOUBLE, wenn wir uns um das niederwertige Bit kümmern. Andererseits wird die Präzision erst in ein paar Jahrhunderten ausgehen.

Mit int64(BIGINT) geht Ihnen die Genauigkeit noch lange nicht aus. Wenn ich tatsächlich Mikrosekunden-Zeitstempel nur für ihre Reihenfolge in MySQL speichern würde, würde ich mich für DATETIME(6) entscheiden weil ich jede Menge Datumsarithmetik umsonst bekommen würde. Wenn ich eine hochvolumige In-Memory-App erstellen würde, würde ich int64 verwenden.