11

我想将 PHP 的 microtime 作为我的时间戳存储在 MySQL 中。

有人告诉我最好将它存放在 中DECIMAL,但我找不到理想的尺寸。

有谁知道microtime(true)返回的最大大小,所以我可以把它作为我的数据类型长度?

我应该选择可变DECIMAL长度吗?

4

4 回答 4

16

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.001epsilon”。

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

或类似的东西。如果将这些时间戳以小数或百万分之一秒的形式存储在bigint列中,则不会出现此问题。

IEEE 64 位浮点具有 53 位尾数——精度。当前的 UNIX 纪元时间戳(自 1970 年 1 月 1 日 00:00Z 以来的秒数)乘以一百万使用 51 位。因此,如果我们关心低位,则 DOUBLE 没有太多额外的精度。另一方面,精度不会用完几个世纪。

使用 int64(BIGINT),您的精度还远远不够。如果我实际上只是为了在 MySQL 中对它们进行排序而存储微秒时间戳,我会选择这样做,DATETIME(6)因为我会免费获得很多日期算术。如果我正在做一个内存大容量应用程序,我会使用 int64。

于 2013-01-08T01:31:32.960 回答
1

这取决于您需要的精度。如果毫秒对您来说足够了,并且您不希望任何大于 999999 秒的运行时可以使用DECIMAL(10,4). 您可以通过这种方式满足您的需求。

关于理论上的最大值,它受float系统上 a 的大小(32 位、64 位)的限制。有关详细信息,请参阅PHP 浮点数。但正如我所说,这是理论上的。没有计时器会给你那个精确的时间。

于 2013-01-08T00:02:15.913 回答
1

在 MySQL 5.6.4 及更高版本中,本机DATETIMETIMESTAMP类型可以支持小数秒。因此,您可以将具有微秒分辨率的时间戳存储在一列DATETIME(6)或一TIMESTAMP(6)列中。

要将 PHPmicrotime()返回值转换为 MySQL 日期时间格式,您可以使用 MySQLFROM_UNIXTIME()函数,或者,如果您使用的是 PHP DateTime 类,则可以使用DateTime::format(). 请注意,PHPdate()函数当前支持微秒时间戳。(它确实有一个微秒的格式代码u,但它总是将它映射到000000。)

对于不能以原生日期时间类型存储微秒的旧 MySQL 版本,您应该使用DOUBLE, BIGINT(以微秒表示的值,即乘以 1,000,000)或DECIMAL(16,6)(这应该足够几百年了)。

于 2013-01-08T01:50:32.167 回答
-1

你为什么不把它存储为一个float?这就是microtime(true)回报,所以它是最好的候选人。

于 2013-01-07T23:57:47.357 回答