sql >> Database teknologi >  >> RDS >> Mysql

DECIMAL længde for mikrotid (sand)?

tl;dr. Brug microtime(false) og gem resultaterne i en MySQL bigint som milliontedele sekunder. Ellers skal du lære alt om floating point aritmetik, som er en stor fed hårbold.

PHP-mikrotidsfunktionen griber Unix-tidsstemplet (i øjeblikket omkring hex 50eb7c00 eller decimal 1.357.609.984) fra et systemkald og mikrosekundtiden fra et andet systemkald. Det gør dem derefter til en tegnstreng. Så, hvis du kalder det med (sandt), konverterer det nummeret til et 64-bit IEEE 745 flydende tal, en ting PHP kalder en float .

Fra i dag skal du bruge ti decimalcifre til venstre for decimaltegnet for at gemme et heltals UNIX-tidsstempel. Det vil forblive sandt indtil omkring 2280 CE, hvor dine efterkommere vil begynde at bruge elleve cifre. Du skal bruge seks cifre til højre for decimalen for at gemme mikrosekunderne.

Du vil ikke få total mikrosekund nøjagtighed. De fleste systemer holder deres systemur på undersekund med en opløsning på noget i intervallet 1-33 millisekunder. Det er systemafhængigt.

MySQL version 5.6.4 og nyere giver dig mulighed for at angive DATETIME(6) kolonner, som vil holde datoer og klokkeslæt til mikrosekundsopløsning. Hvis du bruger sådan en MySQL-version, er det absolut vejen at gå.

Før version 5.6.4 skal du bruge MySQL DOUBLE (IEEE 754 64-bit flydende komma) til at gemme disse tal. MySQL FLOAT (IEEE 754 32-bit floating point) har ikke nok bits i sin mantisse til at gemme selv den nuværende UNIX-tid i sekunder fuldstændig nøjagtigt.

Hvorfor gemmer du disse tidsstempler? Håber du at gøre

  WHERE table.timestamp = 1357609984.100000

eller lignende forespørgsler for at slå bestemte varer op? Det er fyldt med fare, hvis du bruger float- eller dobbelttal hvor som helst i din behandlingskæde (det vil sige, selvom du bruger microtime(true) endda én gang). De er berygtede for ikke at være lige, selv når du troede, de burde. I stedet skal du bruge sådan noget. 0.001 kaldes "epsilon" inden for numerisk forarbejdning.

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

eller noget lignende. Du vil ikke have dette problem, hvis du gemmer disse tidsstempler som decimaler eller i milliontedele sekunder i en bigint kolonne.

IEEE 64-bit flydende komma har 53 bit mantisse -- af præcision. Det nuværende UNIX Epoch-tidsstempel (sekunder siden 1-Jan-1970 00:00Z) gange en million bruger 51 bit. Så der er ikke meget ekstra præcision i DOBBELT, hvis vi bekymrer os om den lave ordens bit. På den anden side vil præcisionen ikke løbe tør før om et par århundreder.

Du er ikke i nærheden af ​​at løbe tør for præcision med int64(BIGINT). Hvis jeg rent faktisk gemte mikrosekunders tidsstempler kun for at bestille dem i MySQL, ville jeg gå med DATETIME(6) fordi jeg ville få masser af datoregning gratis. Hvis jeg lavede en højvolumen-app i hukommelsen, ville jeg bruge int64.



  1. rækkefølge for udførelse i webmiljø

  2. Eksporter tabeldata fra en SQL Server til en anden

  3. hvordan kan man sammenkæde strenge?

  4. Hvordan indsætter man pandas dataramme via mysqldb i databasen?