sql >> Databasteknik >  >> RDS >> Mysql

DECIMAL längd för mikrotid (true)?

tl;dr. Använd microtime(false) och lagra resultaten i en MySQL bigint som miljondelar av sekunder. Annars måste du lära dig allt om flyttalsräkning, vilket är en stor fet hårboll.

PHP-mikrotidsfunktionen tar tag i Unix-tidsstämpeln (för närvarande cirka hex 50eb7c00 eller decimal 1 357 609 984) från ett systemanrop och mikrosekundtiden från ett annat systemanrop. Det gör dem sedan till en teckensträng. Sedan, om du anropar det med (true) det konverterar det numret till ett 64-bitars IEEE 745 flyttal, något PHP kallar en float .

Från och med idag behöver du tio decimalsiffror till vänster om decimaltecknet för att lagra ett heltals UNIX-tidsstämpel. Det kommer att förbli sant fram till omkring 2280 e.Kr. när dina ättlingar kommer att börja behöva elva siffror. Du behöver sex siffror till höger om decimalen för att lagra mikrosekunderna.

Du kommer inte att få total mikrosekund noggrannhet. De flesta system håller sin systemklocka på undersekund med en upplösning på något i intervallet 1-33 millisekunder. Det är systemberoende.

MySQL version 5.6.4 och senare låter dig ange DATETIME(6) kolumner, som kommer att hålla datum och tider till mikrosekunders upplösning. Om du använder en sådan MySQL-version är det absolut rätt väg att gå.

Innan version 5.6.4 måste du använda MySQL DOUBLE (IEEE 754 64-bitars flyttal) för att lagra dessa nummer. MySQL FLOAT (IEEE 754 32-bitars flyttal) har inte tillräckligt med bitar i mantissan för att lagra ens den nuvarande UNIX-tiden i sekunder helt exakt.

Varför lagrar du dessa tidsstämplar? Hoppas du på att göra

  WHERE table.timestamp = 1357609984.100000

eller liknande frågor för att leta upp särskilda föremål? Det är förenat med fara om du använder flytande eller dubbla tal var som helst i bearbetningskedjan (det vill säga även om du använder microtime(true) till och med en gång). De är ökända för att inte komma upp lika även när du trodde att de borde. Istället måste du använda något sådant här. 0.001 kallas "epsilon" inom numerisk bearbetning.

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

eller något liknande. Du kommer inte ha detta problem om du lagrar dessa tidsstämplar som decimaler eller i miljondelar av sekunder i en bigint kolumn.

IEEE 64-bitars flyttal har 53 bitar av mantissa -- av precision. Den nuvarande UNIX Epoch-tidsstämpeln (sekunder sedan 1-jan-1970 00:00Z) gånger en miljon använder 51 bitar. Så det finns inte mycket extra precision i DUBBELT om vi bryr oss om den låga ordningen. Å andra sidan kommer precisionen inte att ta slut på ett par århundraden.

Du är inte i närheten av att få slut på precision med int64(BIGINT). Om jag faktiskt lagrade mikrosekunders tidsstämplar bara för att beställa dem i MySQL, skulle jag gå med DATETIME(6) eftersom jag skulle få massor av datumräkning gratis. Om jag gjorde en app med hög volym i minnet skulle jag använda int64.



  1. Oracle SQL-utvecklarverktyg:nedladdning och installation

  2. Tomcat JDBC Conencton Pool + MySQL ger Broken pipe-problem, även med anslutningsvalidering

  3. Konvertera tidsstämpel datatyp till unix tidsstämpel Oracle

  4. Hur man skyddar MySQL-databaser från Ransomware-kampanjer