I want to store PHP's microtime as my timestamp in MySQL.
I've been told it's best to store it in DECIMAL
, but I can't find an ideal size.
Does anyone know what the maximum size microtime(true)
returns, so I can put that as my data type length?
Should I choose variable DECIMAL
length?
Why don't you just store it as a
float
? That's whatmicrotime(true)
returns, so it's the best candidate.In MySQL 5.6.4 and above, the native
DATETIME
andTIMESTAMP
types can support fractional seconds. Thus, you can store a timestamp with microsecond resolution in aDATETIME(6)
or aTIMESTAMP(6)
column.To convert PHP
microtime()
return values to MySQL datetime format, you can use the MySQLFROM_UNIXTIME()
function or, if you're using the PHP DateTime class,DateTime::format()
. Note that the PHPdate()
function does not currently support microsecond timestamps. (It does have a format code for microseconds,u
, but it always maps it to000000
.)For older MySQL versions, which cannot store microseconds in their native datetime types, you should use either
DOUBLE
,BIGINT
(with the values expressed in microseconds, i.e. multiplied by 1,000,000) orDECIMAL(16,6)
(which should be enough for a few hundred years yet).That depends on the precision you need. If milliseconds are enough for you, and you don't expect any runtimes larger than 999999 seconds you could use
DECIMAL(10,4)
. You can fit it to your needs this way.About the theoretical maximum, it is limited by the size of a
float
on your system (32bit, 64bit). See PHP Float for details. But as I said, that is theoretical. No timer will give you the time in that precision.tl;dr. Use microtime(false) and store the results in a MySQL bigint as millionths of seconds. Otherwise you have to learn all about floating point arithmetic, which is a big fat hairball.
The PHP microtime function grabs the Unix timestamp (currently about hex 50eb7c00 or decimal 1,357,609,984) from one system call, and the microsecond time from another system call. It then makes them into a character string. Then, if you call it with (true) it converts that number to a 64-bit IEEE 745 floating point number, a thing PHP calls a
float
.As of today you need ten decimal digits to the left of the decimal point to store an integer UNIX timestamp. That will remain true until about 2280 CE when your descendants will start needing eleven digits. You'll need six digits to the right of the decimal place to store the microseconds.
You aren't going to get total microsecond accuracy. Most systems keep their sub-second system clock with a resolution of something in the range of 1-33 milliseconds. It's system dependent.
MySQL version 5.6.4 and later allow you to specify
DATETIME(6)
columns, which will hold dates and times to microsecond resolution. If you're using such a MySQL version that's absolutely the way to go.Before version 5.6.4, you need to use MySQL
DOUBLE
(IEEE 754 64-bit floating point) to store these numbers. MySQLFLOAT
(IEEE 754 32-bit floating point) doesn't have enough bits in its mantissa to store even the present UNIX time in seconds completely accurately.Why are you storing these timestamps? Are you hoping to do
or similar queries to look up particular items? That is fraught with peril if you use float or double numbers anywhere in your processing chain (that is, even if you use
microtime(true)
even once). They are notorious for not coming up equal even when you thought they should. Instead you need to use something like this. The0.001
ìs called "epsilon" in the numerical processing trade.or something similar. You won't have this problem if you store these timestamps as decimals or in millionths of seconds in a
bigint
column.IEEE 64-bit floating point has 53 bits of mantissa -- of precision. The present UNIX Epoch timestamp (seconds since 1-Jan-1970 00:00Z) times one million uses 51 bits. So there isn't much extra precision in the DOUBLE if we care about the low-order bit. On the other hand, the precision won't run out for a couple of centuries.
You are nowhere near running out of precision with int64(BIGINT). If I were actually storing microsecond timestamps just for the ordering of them in MySQL, I'd go with
DATETIME(6)
because I'd get lots of date arithmetic for free. If I were doing an in-memory high volume app, I'd use int64.