我想将PHP的microtime存储为MySQL中的时间戳。
我一直told最好将它存储在DECIMAL
中,但我找不到理想的尺寸。
有谁知道最大大小microtime(true)
返回什么,所以我可以把它作为我的数据类型长度?
我应该选择变量DECIMAL
长度吗?
答案 0 :(得分:14)
TL;博士。使用microtime(false)并将结果存储在MySQL bigint中,以百万分之一秒为单位。否则你必须学习浮点运算,这是一个很大的毛球。
PHP microtime函数从一次系统调用中获取Unix时间戳(当前约为十六进制50eb7c00或十进制1,357,609,984),以及另一次系统调用的微秒时间。然后它将它们变成一个字符串。然后,如果你用(true)调用它,它将该数字转换为64位IEEE 745浮点数,PHP称之为float
。
截至今天,您需要在小数点左侧使用十位十进制数来存储整数UNIX时间戳。直到大约公元2280年,当你的后代开始需要11位数时,这种情况仍然存在。你需要在小数点右边六位数来存储微秒。
您不会获得总微秒精度。大多数系统保持其亚秒级系统时钟的分辨率在1-33毫秒的范围内。它取决于系统。
MySQL 5.6.4及更高版本允许您指定DATETIME(6)
列,这些列将日期和时间保持为微秒分辨率。如果您正在使用这样的MySQL版本,那绝对是可行的方法。
在5.6.4版之前,您需要使用MySQL DOUBLE
(IEEE 754 64位浮点)来存储这些数字。 MySQL FLOAT
(IEEE 754 32位浮点)在其尾数中没有足够的位来完全准确地存储甚至当前的UNIX时间(以秒为单位)。
为什么要存储这些时间戳?你希望做什么
WHERE table.timestamp = 1357609984.100000
或类似查询以查找特定项目?如果你在处理链的任何地方使用浮点数或双数字(即使你曾经使用microtime(true)
一次),那就充满了危险。即使你认为应该这样做,他们也因为不平等而臭名昭着。相反,你需要使用这样的东西。 0.001
在数字处理行业中被称为“epsilon”。
WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
AND 1357609984.100000 + 0.001
或类似的东西。如果将这些时间戳存储为bigint
列中的小数或百万分之一秒,则不会出现此问题。
IEEE 64位浮点有53位尾数 - 精度。当前的UNIX Epoch时间戳(自1970年1月1日 - 00:00Z以来的秒)乘以100位使用51位。因此,如果我们关心低阶位,那么DOUBLE中没有太多额外的精度。另一方面,精度不会耗尽几个世纪。
使用int64(BIGINT),你的精度已经差一点了。如果我实际上只是为了在MySQL中对它们进行排序来存储微秒时间戳,我会选择DATETIME(6)
,因为我会免费获得大量的日期算术。如果我正在使用内存大批量应用,我会使用int64。
答案 1 :(得分:1)
这取决于您需要的精度。如果毫秒足够您,并且您不希望任何大于999999秒的运行时间,则可以使用DECIMAL(10,4)
。你可以通过这种方式满足你的需求。
关于理论最大值,它受系统中float
的大小限制(32位,64位)。有关详细信息,请参阅PHP Float。但正如我所说,这是理论上的。没有计时器会给你精确的时间。
答案 2 :(得分:1)
在MySQL 5.6.4及更高版本中,the native DATETIME
and TIMESTAMP
types can support fractional seconds。因此,您可以在DATETIME(6)
或TIMESTAMP(6)
列中存储微秒分辨率的时间戳。
要将PHP microtime()
返回值转换为MySQL日期时间格式,您可以使用MySQL FROM_UNIXTIME()
函数,或者,如果您使用的是PHP DateTime类,则DateTime::format()
。请注意,PHP date()
函数不目前支持微秒时间戳。 (它确实有一个微秒的格式代码u
,但它始终将其映射到000000
。)
对于较旧的MySQL版本,它们无法在其原生日期时间类型中存储微秒,您应该使用DOUBLE
,BIGINT
(以微秒表示的值,即乘以1,000,000)或{{1 (这应该足够几百年了)。
答案 3 :(得分:-1)
为什么不将它存储为float
?这就是microtime(true)
返回的内容,因此它是最佳候选者。