sql >> Databáze >  >> RDS >> Mysql

DECIMÁLNÍ délka pro mikročas (pravda)?

tl;dr. Použijte microtime (false) a ukládejte výsledky v MySQL bigint jako miliontiny sekund. Jinak se musíte naučit vše o aritmetice s pohyblivou řádovou čárkou, což je velká tlustá koule.

Mikročasová funkce PHP získává časové razítko Unixu (aktuálně asi hex 50eb7c00 nebo desetinné číslo 1 357 609 984) z jednoho systémového volání a mikrosekundový čas z jiného systémového volání. Poté z nich vytvoří řetězec znaků. Pak, když to zavoláte s (true), převede to číslo na 64bitové IEEE 745 číslo s pohyblivou řádovou čárkou, což PHP nazývá float .

K dnešnímu dni potřebujete deset desetinných číslic nalevo od desetinné čárky k uložení celočíselného časového razítka UNIX. To bude platit až do roku 2280, kdy vaši potomci začnou potřebovat jedenáct číslic. K uložení mikrosekund budete potřebovat šest číslic napravo od desetinného místa.

Nezískáte úplnou mikrosekundovou přesnost. Většina systémů udržuje své subsekundové systémové hodiny s rozlišením v rozmezí 1-33 milisekund. Je to závislé na systému.

MySQL verze 5.6.4 a novější vám umožňují zadat DATETIME(6) sloupce, které budou obsahovat data a časy v mikrosekundovém rozlišení. Pokud používáte takovou verzi MySQL, je to naprosto správná cesta.

Před verzí 5.6.4 musíte MySQL používat DOUBLE (IEEE 754 64-bit s pohyblivou řádovou čárkou) pro uložení těchto čísel. MySQL FLOAT (IEEE 754 32-bit s plovoucí desetinnou čárkou) nemá v mantise dostatek bitů na to, aby zcela přesně uložil i současný UNIXový čas v sekundách.

Proč ukládáte tato časová razítka? Doufáte, že uděláte

  WHERE table.timestamp = 1357609984.100000

nebo podobné dotazy k vyhledání konkrétních položek? To je plné nebezpečí, pokud kdekoli v řetězci zpracování použijete plovoucí nebo dvojitá čísla (to znamená, i když používáte microtime(true) ani jednou). Jsou proslulí tím, že si nejsou rovni, i když jste si mysleli, že by měli. Místo toho musíte použít něco takového. 0.001 V obchodě s numerickým zpracováním se nazývá "epsilon".

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

nebo něco podobného. Tento problém nebudete mít, pokud tato časová razítka uložíte jako desetinná místa nebo v miliontinách sekund v bigint sloupec.

64bitová IEEE s plovoucí desetinnou čárkou má 53 bitů mantisy -- přesnost. Současná časová značka UNIX Epoch (sekundy od 1. ledna 1970 00:00 Z) krát jeden milion používá 51 bitů. Takže v DOUBLE není moc extra přesnosti, pokud nám záleží na bitu nízkého řádu. Na druhou stranu přesnost nevyprší za několik století.

S int64(BIGINT) vám ani zdaleka nedojde přesnost. Pokud bych ve skutečnosti ukládal mikrosekundová časová razítka pouze pro jejich uspořádání v MySQL, použil bych DATETIME(6) protože bych získal spoustu datové aritmetiky zdarma. Pokud bych dělal aplikaci s velkým objemem v paměti, použil bych int64.



  1. Vyberte nabídku možností čtení z databáze a použijte její hodnoty

  2. Jak nastavit MariaDB, aby používala vertikální výstup

  3. datový typ mysql pro uložení pouze měsíce a roku

  4. Jak by DevOps měli používat DBaaS (databáze jako služba) k optimalizaci vývoje svých aplikací​