MySQL的datetime和timestamp字段对于PHP应用程序来说比Unix时间戳整数更好吗?

8
我正在阅读一篇文章,其中展示了关于三种不同的MySQL日期/时间存储选项的性能信息和基准测试。

MySQL DATETIME vs TIMESTAMP vs INT performance and benchmarking with MyISAM

在阅读这篇文章时,你会开始认为使用整数是浪费,而应该选择MySQL Datetime或Timestamp列类型。

然而,在文章末尾,他进行了一次没有使用MySQL函数的测试,你突然看到直接使用INT在搜索Unix时间戳时比两个MySQL选项快2倍

所以我突然想到 - duh,所有PHP应用程序都使用什么?time()! 几乎每个php应用程序都基于Unix纪元计算逻辑。这意味着大多数查询某个时间段内的结果都是基于time()开始的,然后转换为与MySQL字段配合使用

这让我有以下想法:

  1. 将Unix时间戳存储为INT类型更快,占用空间更少,并且可以与PHP的基于time()的计算原生工作。

  2. MySQL日期类型更适合MySQL侧的操作和逻辑。

  3. 目前Unix和MySQL时间戳仅适用于2037年之前,这意味着您必须使用datetime字段来处理未来较大的日期。

  4. 使用复制时,像date = NOW()这样的MySQL命令可能会滞后,导致数据不一致。

因此,将其应用于实际生活中,我们发现答案是,大多数真正的DBA都会使用更好的引擎,例如PostgreSQL。然而,大多数使用DB逻辑的应用程序可能会选择PostgreSQL。这意味着我们其他程序员只使用MySQL作为数据存储罐(您知道这是真的),这使得保持字段小,快速,UNIX INT似乎实际上是最佳选择。

那么你们觉得呢?

时间戳是否真的比MySQL日期字段更适合PHP应用程序?


3
我不喜欢使用整数时间戳,因为在即席查询中阅读它们很困难。 - Byron Whitlock
我相信在2038年之前,64位平台的市场渗透率会更好。在存储Unix时间时,请使用time_t而不是int - sarnold
请查看https://dev59.com/X3E95IYBdhLWcg3wadKq#2324112。 - Alexar
对于即席查询,如果您有一个整数时间戳,请在日期上执行 from_unixtime() - JAL
1
我相信在2038年之前,1024位平台的市场渗透率会更好。 - Xeoncross
另外,不要使用unsigned int(),因为它没有任何作用:https://dev59.com/C2855IYBdhLWcg3wiU31 - Xeoncross
6个回答

9

MySQL的日期格式没有2038年问题。

MySQL的日期从公元1000年到9999年都是可靠的,而Unix时间戳在2038年之后或1902年之前可能会出现问题,除非您的系统中所有内容都是64位的。

然而,如果您使用PHP,则可能无关紧要:PHP在其大多数日期和时间函数中使用Unix时间戳,除非您使用的是64位版本,否则它将具有相同的限制。

您应该使用为此目的设计的字段类型。

如果您关心的话。将日期作为Unix时间戳放入INT字段中并不是很自我描述;您不能在不适当地转换数据的情况下查看数据。但这可能对您没有影响。

另一方面,鉴于您使用的是PHP,一旦将时间传递给PHP,您仍然需要将其转换回Unix时间戳才能对其进行任何有用的操作,因为对于PHP来说,Unix时间戳是本机的。

编辑:

当我撰写此答案时,我没有使用PHP的DateTime类。使用DateTime类可以消除使用Unix时间戳的任何需要,并消除32/64位问题。感谢下面Charles的评论指出了一个好方法。


14
现代PHP的DateTime类内部使用64位时间戳,不会受到Y2038问题的影响。构造函数使用strtotime来解析传递的时间戳,并且能够理解MySQL的日期时间格式而不需要任何强制转换。新的、现代化的PHP应用程序应该使用DateTime而不是整数时间戳。 - Charles
现在,那个评论值得成为一个答案。我真的需要转移到DateTime类(和其他类),但我还没有这样做。 - Xeoncross

1

使用MySQL的各种时间和日期格式允许查询Unix时间戳难以完成的内容。

例如,基于特定周(周数)筛选数据,或者在从数据库中添加或删除某个时间段后使用值等。

MySQL有一些非常好用的函数用于时间和日期操作,可与日期、日期时间和时间格式配合良好。

我们大多数网站都使用PHP/MySQL,并自动化数据库到PHP对象的创建。从PHP转换为MySQL格式的代码非常简单:

if($parameter->Type() == DatabaseType::DATETIME)
    $parameterValueArray[] = date('Y-m-d H:i:s', $parameter->Value());
elseif($parameter->Type() == DatabaseType::DATE)
    $parameterValueArray[] = date('Y-m-d', $parameter->Value());
elseif($parameter->Type() == DatabaseType::TIME)
    $parameterValueArray[] = date('H:i:s', $parameter->Value());

MySQL 到 PHP:

strtotime() 用于日期时间 mktime() 用于时间和日期


使用Unix时间戳来进行一周搜索,例如date > time + week OR date < time - week确实比date = CURTIME(w)更麻烦。不过,你需要额外添加逻辑来保存和检索值,因为它不再是PHP内置的功能。 - Xeoncross
绝对的,虽然没有完美的解决方案。PHP 与 Unix 时间配合非常好,MySQL 与其自己的格式配合也很好。在我看来,两者之间建立一个桥梁是最好的解决方案。我曾经参与过一些只依赖 Unix 时间的项目,这使得调试数据库问题变得更加困难,并且不支持像 1970 年之前的生日等事情! - Simon

1
很好的开放式问题。我看到你是个完美主义者,我也是。
但几乎所有编程和生活中的事情都取决于它如何适应您的问题。
如果性能真的非常关键,您应该使用UNIX时间戳。
但我真的不认为这是这种情况。我告诉你原因。这是因为我与Rasmus Lerdorf持有相同的观点。PHP是一种脚本语言,为中小型企业带来了许多便利。
对于真正重要/大的应用程序,其中可伸缩性和性能真正重要,您根本不应使用PHP + MySQL。
Java或C ++是更好的解决方案。我认为这里的大多数人会问“你这混蛋,PHP有什么问题?!”实际上,有很多问题。我曾经担任过性能测试员,我说开发者应该记住,您最喜欢的语言并不总是每个问题的最佳解决方案。
让我举个例子。一个关键的数学/物理应用程序。只需要一个现象分析的数字。您可以在Shell脚本和C上执行此操作。 C将表现得更好。选择最合适的语言和工具来适应您的问题是您的正确答案的答案。

让我们回到MySQL、PHP和数据类型。如果你正在使用这些,我想应用程序不是很大,也没有太多的业务规则(如果很大,你会考虑一些编译型语言,如果非常关键,你应该考虑使用PostgreSQL或Oracle)。

在这种情况下,最重要的是建立应用程序的速度。如果你这样做,我认为一个好的起点是基于数据库元数据构建表单字段。这可以帮助你自动化表单构建。在这种情况下,我建议使用本地数据库类型。


是的,我猜当你的项目足够大时,你可能会转向提供更高速度的低级语言。然而,我从未见过公司这样做。看看 Facebook、Twitter 或 Digg。当 Web 应用程序变得更大时,它们不会移动,原因是 PHP/Ruby "允许他们更快地迭代"。例如,Facebook 刚刚构建了 HipHop,这样他们就不必转向 C++,即使它更快 - 解析器将自动为他们完成。 - Xeoncross
然而,我仍然不相信使用MySQL datetime字段可以更好地使用MySQL内置的时间函数进行排序 - 只需使用time() - ###!速度更快,而且所有逻辑都放在代码库的一个部分。 - Xeoncross
经过一些规划、测试和重构,该网站最终达到了68000个并发用户的限制,远比之前好多了。另一个我必须提到的是:尽管Facebook将他们的代码保留在PHP上,但我认为可以合理地假设他们的后端不像大多数网站那样简单,无论是基础设施还是编码方面。你可以打赌他们有一个不错的CDN,分叉线程,数据库冗余,连贯的数据设计,强大的缓存,精心设计的类,智能利用资源等等。 - Davis Peixoto
然而,我认为你的最后一条评论是基于我最后一段所说的内容,并且我们在那个地方产生了误解。我在谈论表单构建自动化流程,即市场上大多数框架/ORM都有的流程,甚至是高质量的手工解决方案。而我认为你谈论的是某些特定语句的速度。如果是这样的话,我不能不提到长尾理论及其在网站优化中的应用,例如使用图像精灵(一个单独的图像文件和CSS定位)而不是多个图像文件。 - Davis Peixoto
是的,Facebook已经声明他们网站98%的内容都是由缓存数据运行的。 - Xeoncross
显示剩余3条评论

1

我总是更喜欢使用mySQL格式存储日期,因为这样可以使查询中的比较更简单。 mySQL还有一些很棒的日期格式化选项: http://www.dan.co.uk/mysql-date-format/

抱歉,我应该补充说明,我真的不知道哪种速度更高效,这是你问题的一个重要部分。


1

我喜欢将所有逻辑保留在单个高级域中(即用PHP编写的应用程序)。MySQL是一个存储容器 - 应该保持这样。我更喜欢使用类似于http://www.symfony-project.org/plugins/sfDateTime2Plugin的类,然后使用-dump()或-get()转换为适当的格式。在应用程序域中编写(和扩展)高级操作比使用静态mysql接口要快得多,也更容易。

PostgreSQL的接口比MySQL更清晰。但我们仍然在谈论MySQL,因为它很受欢迎。这带来了一个重要的考虑因素。在编写代码或设计系统时,通常最好遵守惯例,即使它不如其他不太知名的选项计算效率高。这很重要,因为它有利于另一种效率 - 对他人的可读性。通常,可读性和理解能力的低效会导致更大的业务费用(和时间),而不是计算效率低下。

我完全支持尝试INTs。请尝试并写下您的发现。

干杯


0

如果您使用INT而不是DATETIME,您将失去按日期、小时或时间进行GROUP的灵活性,从而使不同的间隔操作变得困难。

您可以使用函数FROM_UNIXTIME来使用INT,但是您的查询将变得难以阅读。

使用INT而不是DATE会使您的编程成本增加三倍,而与DATE一起工作则不然。虽然节省了执行时间,但无法弥补编程成本。硬件比复杂编程更便宜。

我们曾经犯过这个错误,将日期保存在INT中。半年后,我们决定对30个站点进行重构以便于维护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接