sql >> Database >  >> RDS >> Mysql

DECIMALE lengte voor microtime(true)?

tl;dr. Gebruik microtime(false) en sla de resultaten op in een MySQL-bigint als miljoensten van seconden. Anders moet je alles leren over rekenkunde met drijvende komma, wat een grote vette haarbal is.

De PHP-microtimefunctie haalt de Unix-tijdstempel (momenteel ongeveer hexadecimaal 50eb7c00 of decimaal 1.357.609.984) van de ene systeemaanroep en de microsecondetijd van een andere systeemaanroep. Het maakt ze vervolgens tot een tekenreeks. Als je het vervolgens met (true) aanroept, converteert het dat getal naar een 64-bits IEEE 745 floating point-nummer, iets wat PHP een float noemt. .

Vanaf vandaag heb je tien decimale cijfers links van de komma nodig om een ​​integer UNIX-tijdstempel op te slaan. Dat blijft zo tot ongeveer 2280 CE wanneer uw nakomelingen elf cijfers nodig zullen hebben. Je hebt zes cijfers rechts van de komma nodig om de microseconden op te slaan.

Je krijgt geen totale nauwkeurigheid van microseconden. De meeste systemen behouden hun systeemklok van minder dan een seconde met een resolutie van iets in het bereik van 1-33 milliseconden. Het is systeemafhankelijk.

Met MySQL versie 5.6.4 en hoger kunt u DATETIME(6) . specificeren kolommen, die datums en tijden bevatten tot een resolutie van microseconden. Als je zo'n MySQL-versie gebruikt, is dat absoluut de beste keuze.

Vóór versie 5.6.4 moet u MySQL DOUBLE gebruiken (IEEE 754 64-bit floating point) om deze nummers op te slaan. MySQL FLOAT (IEEE 754 32-bit floating point) heeft niet genoeg bits in zijn mantisse om zelfs de huidige UNIX-tijd in seconden volledig nauwkeurig op te slaan.

Waarom bewaart u deze tijdstempels? Hoop je te doen

  WHERE table.timestamp = 1357609984.100000

of soortgelijke vragen om bepaalde items op te zoeken? Dat is gevaarlijk als u overal in uw verwerkingsketen float- of dubbele getallen gebruikt (dat wil zeggen, zelfs als u microtime(true) gebruikt zelfs eens). Ze zijn berucht omdat ze niet gelijk komen, zelfs als je dacht dat ze dat zouden moeten doen. In plaats daarvan moet je iets als dit gebruiken. De 0.001 In de numerieke verwerking wordt het "epsilon" genoemd.

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

of iets dergelijks. U zult dit probleem niet hebben als u deze tijdstempels opslaat als decimalen of in miljoensten van seconden in een bigint kolom.

IEEE 64-bit floating point heeft 53 bits mantisse -- van precisie. De huidige UNIX Epoch-tijdstempel (seconden sinds 1 januari 1970 00:00Z) maal één miljoen gebruikt 51 bits. Dus er is niet veel extra precisie in de DOUBLE als we om het lage-orde bit geven. Aan de andere kant zal de precisie pas over een paar eeuwen opraken.

Met int64(BIGINT) kom je niet in de buurt van je precisie. Als ik tijdstempels van microseconden zou opslaan alleen om ze in MySQL te bestellen, zou ik voor DATETIME(6) gaan omdat ik veel datumberekeningen gratis zou krijgen. Als ik een in-memory app met hoog volume zou gebruiken, zou ik int64 gebruiken.



  1. Selecteer een willekeurige rij uit een PostgreSQL-tabel met gewogen rijkansen

  2. Mijn Select SUM-query retourneert null. Het zou 0 . moeten retourneren

  3. WordPress linkt alle doorverwijzingen naar dubbele URL

  4. GROUP BY en geaggregeerde sequentiële numerieke waarden