具有毫秒精度的时间戳:如何将它们保存在 MySQL 中

Posted

技术标签:

【中文标题】具有毫秒精度的时间戳:如何将它们保存在 MySQL 中【英文标题】:Timestamp with a millisecond precision: How to save them in MySQL 【发布时间】:2014-12-05 14:34:28 【问题描述】:

我必须使用 mysql 开发应用程序,并且必须保存诸如“1412792828893”之类的值,这些值表示时间戳,但精度为毫秒。也就是说,自 1.1.1970 以来的毫秒数。我将该行声明为timestamp,但不幸的是这不起作用。所有值都设置为0000-00-00 00:00:00

CREATE TABLE IF NOT EXISTS `probability` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`segment_id` int(11) NOT NULL,
`probability` float NOT NULL,
`measured_at` timestamp NOT NULL,
`provider_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ;

应该如何声明才能以这种精度保存时间戳值?

【问题讨论】:

什么版本的 MySQL? mysql Ver 14.14 Distrib 5.6.11,适用于 Win32 (x86) 看来你很幸运。 您手头有插入前几毫秒的值吗?如果是这样,为什么不直接存储为 BIGINT? 【参考方案1】:

您需要使用 MySQL 5.6.4 或更高版本才能声明具有小数秒时间数据类型的列。不确定您的版本是否正确?试试SELECT NOW(3)。如果出现错误,则说明版本不正确。

例如,DATETIME(3) 将为您的时间戳提供毫秒分辨率,TIMESTAMP(6) 将为您提供 *nix 样式时间戳的微秒分辨率。

阅读:https://dev.mysql.com/doc/refman/8.0/en/fractional-seconds.html

NOW(3) 将为您提供 MySQL 服务器操作系统的当前时间,精度为毫秒。

如果自 Unix epoch 之后的毫秒数,请尝试此操作以获取 DATETIME(3) 值

FROM_UNIXTIME(ms * 0.001)

例如,javascript timestamps 以自Unix epoch 起的毫秒数表示。

(请注意,MySQL 内部的小数运算,如 * 0.001,始终作为 IEEE754 双精度浮点数处理,因此在太阳变成白矮星之前您不太可能失去精度。)

如果您使用的是旧版本的 MySQL,并且需要亚秒级时间精度,那么最好的方法是升级。其他任何事情都会迫使您做出混乱的解决方法。

如果由于某种原因无法升级,您可以考虑使用 BIGINTDOUBLE 列来存储 Javascript 时间戳,就像它们是数字一样。 FROM_UNIXTIME(col * 0.001) 仍然可以正常工作。如果您需要将当前时间存储在这样的列中,您可以使用UNIX_TIMESTAMP() * 1000

【讨论】:

我已将我的定义更改为 timestamp(6),但尝试使用此语法添加值时 INSERT INTO probability (measured_at,probability,provider_id,segment_id) VALUES(1412877161519,0.7418073347680607,1,211623) ;我仍然在“measured_at”列中得到 0000-00-00 00:00:00.00000。我应该如何向这个表中插入值? @Luixv 您需要在输入过程中转换值:INSERT ... VALUES(FROM_UNIXTIME(0.001 * 1412877161519), 0.7418 ... ); 乘以 0.001 是救命稻草!我永远无法猜到它会在不丢失第二个分数的情况下起作用。谢谢。 就我而言,因为我正在使用树莓派进行测试(在 RPI 中安装 mysql 5.6 确实很麻烦,所以我将信息保存为 unix 时间。跨度> 【参考方案2】:
CREATE TABLE fractest( c1 TIME(3), c2 DATETIME(3), c3 TIMESTAMP(3) );

INSERT INTO fractest VALUES
('17:51:04.777', '2018-09-08 17:51:04.777', '2018-09-08 17:51:04.777');

【讨论】:

【参考方案3】:

请通过同样提及时间戳timestamp(2)timestamp(3)timestamp(5) 的长度(长度可以是您想要的以毫秒为单位的任何位数)来创建这样的表。 Mysql 版本应为 5.6 或以上。 https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html

CREATE TABLE IF NOT EXISTS `probability` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`measured_at` timestamp(2) NOT NULL,
 PRIMARY KEY (`id`)
) ;

然后通过 Java 传递时间戳。

statement.setTimestamp(2, new Timestamp(new Date().getTime()))

【讨论】:

【参考方案4】:

您可以按如下方式使用 BIGINT:

CREATE TABLE user_reg (
user_id INT NOT NULL AUTO_INCREMENT,
identifier INT,
phone_number CHAR(11) NOT NULL,
verified TINYINT UNSIGNED NOT NULL,
reg_time BIGINT,
last_active_time BIGINT,
PRIMARY KEY (user_id),
INDEX (phone_number, user_id, identifier)
   );

【讨论】:

BIGINT 是 8 个字节。没有比这更有效的了吗?这就像每条记录比您需要的多两个字节

以上是关于具有毫秒精度的时间戳:如何将它们保存在 MySQL 中的主要内容,如果未能解决你的问题,请参考以下文章

如何在蜂巢中获得毫秒精度?

如何在 Redshift 中将时间戳(具有毫秒)转换为 EPOCH

如何将 Mysql 时间戳转换为 sysdate(6) 格式(以毫秒为单位)?

如何以毫秒为单位获取firebase服务器的当前时间戳?

BinLog 中的时间戳是不是可以达到毫秒精度?

防止 Excel 在时间戳中舍入微秒