该updated
列创建为
| updated | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
一个简单的SELECT
给
+---------------------+
| updated |
+---------------------+
| 2021-12-25 00:15:47 |
+---------------------+
不幸的是,updated
没有创建为timestamp(3)
.
有什么方法可以从中提取更多的准确性updated
?(MySQL 是否存储比秒更高的精度,即使它只显示秒数?)
不可以。无法选择表格中不存在的数据,并且无法根据表格中存在的数据进行计算。
不,它完全存储了您要求的内容。它最多可以存储微秒 - 但您没有要求这种准确性。
你打电话
NOW()
- 你得到没有毫秒的日期时间。调用NOW(3)
orNOW(6)
并获得更准确的值。https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=ccaf9b2c25e372c7bf0ca82c66ded787
永远不要再咨询那个说这种废话的 MySQL 阵营的人。
<TL;DR>
先回答问题:
我的研究强烈表明,如果没有指定精度,则无法恢复比最初存储在字段中更多的数据(这是
TIMESTAMP(0)
()的默认值)(请参阅下面的讨论)。p
可以肯定地说,这是因为如果查看此处各种类型的存储要求,您会看到:
在此之下,您将看到:
因此,我从中得到的是,如果您选择不以
TIMESTAMP
高于 0 的精度专门存储 s,那么您将失去所有更高的精度,因为没有为该额外精度保留空间。一个完全确定的答案将需要一个十六进制编辑器和所有家庭探索
.ibd
文件的乐趣和/或通过 MySQL 的源代码拖网,这两者都比我的工资等级高一点!我认为您可以认为您的额外精度已经消失,或者更确切地说,它从一开始就不存在!</TL;DR>
在评论中犯了一些错误(自删除以来),我决定实际测试(正如他在他自己的回答下的评论中所建议的那样)我的断言(mea culpa, mea maxima culpa)。
我很高兴地报告我对舍入问题是正确的 - 如果插入一个精度为 6 秒的时间,则该值将被舍入而不被截断。
下面的所有代码(除非另有说明)都可以在此处的小提琴中找到。
MySQL
TIMESTAMP
和时区!对于 MySQL,TIMESTAMP 存储为自 UTC 以来的秒数 - 从这里开始:
顺便说一句,这里
TIMESTAMP
还有另一个小提琴,它显示了 MySQL和之间的区别DATETIME
——后一种数据类型没有时区。我强烈敦促您(或任何开发人员)在可能的情况下始终使用 UTC 来存储时间 - 它更简单、更清洁,并且服务器会为您处理夏令时 (DST)。
此外,如果您必须使用本地时区,请不要使用偏移量(小提琴中的 +07:00),因为这样您会丢失任何 DST 信息 - 我这样做的原因是因为 db<>fiddle 的 MySQL 实现不支持时区(请参见此处),但它确实支持偏移量。
更多关于 MySQL的信息
TIMESTAMP
:无论如何,让我感到震惊的第一件事是
TIMESTAMP
没有精确度的事实TIMESTAMP(0)
,但这是在手册中:从这里开始:
很公平,但他们至少
[could | should]
有一个服务器 SQL 模式设置来覆盖它,并将其更改为 SQL 标准行为——他们以前为一堆其他 MySQL 主义做过这个!另一个棘手的问题(但再次记录在案)是
ROUND
当您尝试将较高精度的分数压缩到较低精度的字段时会发生 ing :MySQL的行为:
因此,现在,我们将检查实际行为如下:
然后,填充它:
然后我们检查我们的数据:
结果:
因此,我们可以看到(如记录的那样)
TIMESTAMP
和TIMESTAMP(0)
(无论如何都是相同的)都从15.567899
to向上16
舍入,并且根据指定的精度,这种舍入继续向下行 - 根据手册!那么,如何补救呢?
有两种可能性-第一种是您正在从某个地方进行旧的 TIMESTAMP(6) 测量,并且您需要截断(而不是舍入它们-参见主要小提琴),和/或可能,您可能想要用作
TIMESTAMP(3)
您的字段类型和NOW(3)
您的输入(不同的小提琴)。这些将需要截断
TIMESTAMP(6)
字段中的值。事实证明,这比看起来要棘手 - 请参阅各个阶段的小提琴,但我能想到的最好的方法是:这可能看起来有点像绕房子转,但是 MySQL
DATE_FORMAT
函数具有微秒粒度,但(奇怪的是)不是毫秒!欢迎任何关于更简单、更优雅的解决方案的建议!然后可以将该值插入 ap = 3
TIMESTAMP
(参见fiddle)。(手册)说:
所以,快乐的日子。并检查(小提琴):
插入八个
NOW(p)
值:接着:
结果:
我们可以从上面的示例中看到,如果发生舍入,则
w
字段 (NOW(3)
) 将被舍入到,19:28:38.629
因为以下7
. 为了使这一点变得明显,可能需要运行几次小提琴!磁盘大小:
我试图找到一个查询来获取磁盘上 MySQL 字段的各个大小,但 MySQL 显然没有公开这些信息——至少不是通过它的 SQL 接口。PostgreSQL 具有该
pg_column_size()
功能,并且还有pageinspect
contrib 扩展,供那些喜欢使用 hex dumps 和bit-twiddling 的人使用。除了获得十六进制编辑器和/或深入研究 MySQL 的源代码之外,我能想到的最好的方法是这样的(见小提琴底部):
结果:
因此,8 条记录需要 16kB。快速搜索显示(手册):
在同一页面上,提到了innodb_page_size:
结果:
所以,
Data Length...
上面的所有查询都告诉我们,我们已经为一个小表使用了 1 页磁盘空间——这不足为奇,也没有太多帮助。请参阅我在<TL;DR>
介绍中关于存储要求的讨论,以了解为什么(很可能)您的额外精度位已经进入了天空中的那个大桶...... de profundis ......。