【问题标题】:Are MySQL datetime and timestamp fields better for PHP apps then Unix timestamp ints?PHP 应用程序的 MySQL 日期时间和时间戳字段是否比 Unix 时间戳整数更好?
【发布时间】:2011-03-19 22:24:59
【问题描述】:

我正在阅读一篇文章,该文章展示了一些非常好的信息和基准,说明了三种不同的 MySQL 日期/时间存储选项的性能。

MySQL DATETIME vs TIMESTAMP vs INT performance and benchmarking with MyISAM

在阅读本文时,您开始意识到使用 int 只是一种浪费,您应该改用 MySQL Datetime 或 Timestamp 列类型。

然而,在文章的最后,他又做了一个不使用 MySQL 函数的测试,您突然发现,在通过 unix 时间戳搜索时,直接 INT 的速度是两个 MySQL 选项的 2 倍。

所以我突然明白了 - 呃,PHP 应用程序都使用什么? time()! 几乎每个 php 应用程序的逻辑都基于 Unix 纪元。这意味着在特定时间对结果的大多数查询都是基于 time()开始的,然后被转换为使用 MySQL 的字段。

这给我留下了以下内容:

  1. 存储为 INT 的 Unix 时间戳是 更快,占用更少空间和工作 原生基于 PHP 的 time() 计算。

  2. MySQL 日期类型更适合 来自 MySQL 的操作和逻辑 一边。

  3. 暂时 Unix 和 MySQL 时间戳只工作到 2037 这意味着您必须使用 较大日期的日期时间字段 未来。

  4. date = NOW() 等 MySQL 命令在以下情况下可能会滞后 使用复制导致数据不一致。

因此,将其应用到现实生活中,我们会看到答案 鉴于大多数真正的 DBA 会使用像 PostgreSQL 这样更好的引擎,这些结果 - 有没有 arny

但是,大多数使用数据库逻辑级别的应用程序可能会使用 PostgreSQL。这意味着我们所有其他程序员只将 MySQL 用作我们数据的存储罐(你知道这是真的),这使得字段保持小而快,UNIX INT 看起来就像它实际上是最佳选择。

那你们觉得呢?

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

【问题讨论】:

  • 我不喜欢 int 时间戳,因为在临时查询中读取它们很困难。
  • 我敢肯定,在 2038 年之前,64 位平台的市场渗透率会更高。 (使用time_t,而不是int,用于存储Unix 时间。)
  • 对于临时查询,如果您有一个 int 时间戳,只需在日期执行 from_unixtime()..
  • 我敢肯定,在 2038 年之前,1024 位平台的市场渗透率将会更高。

标签: php mysql timestamp int


【解决方案1】:

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 在下面的评论中指出了使用它的好方法。

【讨论】:

  • 现代 PHP 的 DateTime 类在内部使用 64-bit timestamp 并且不受 Y2038 错误的影响。构造函数使用strtotime解析传递过来的时间戳,并且理解MySQL的日期时间格式,没有任何强制。新的现代 PHP 应用程序应该使用 DateTime 而不是整数时间戳。
  • 现在,该评论值得回答。我真的需要转到 DateTime 类(和其他类),但我还没有这样做。
【解决方案2】:

很好的开放性问题。我看你是个完美主义者。我也是。

但就像编程和生活中的几乎所有事情一样,这取决于它如何适合您的问题。

如果性能真的很关键,您应该使用 UNIX 时间戳。

但我真的不这么认为。我告诉你为什么。这是因为我与拉斯穆斯·勒多夫有着相同的观点。 PHP 是一种脚本语言,它为中小型企业带来了许多便利。

对于真正非常关键/大型应用程序,可伸缩性和性能非常重要,您根本不应该使用 PHP + MySQL。

Java 或 C++ 是更好的解决方案。我想这里的大多数人都会问“PHP 有什么问题,你的混蛋?!”。嗯,其实很多东西。我做过一段时间的性能测试员,我说开发人员应该记住,你最喜欢的语言并不总是解决所有问题的最佳解决方案。

让我举个例子。一个关键的数学/物理应用程序。只需要一个数字来进行现象分析。您可以在 Shell Script 和 C 上执行此操作。C 的性能要好得多。看,选择最适合您的问题的语言和工具就是您正确答案的答案。

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

在这种情况下,重要的是构建应用程序的速度。如果你这样做,我认为一个好的开始方法是让你的表单字段基于数据库元数据。这可以帮助您自动化表单构建。在这种情况下,我建议使用原生数据库类型。

【讨论】:

  • 没错,我想当你变得足够大时,你可能会转向速度更快的低级语言。但是,我实际上从未见过一家公司这样做。看看 Facebook、Twitter 或 Digg。当 Web 应用程序变大时,出于某种原因它们不会移动 - 他们说这是因为 PHP/Ruby “允许它们更快地迭代”。例如,Facebook 刚刚构建了 HipHop,这样他们就不必迁移到 C++ 即使它更快 - 解析器会自动为他们做这件事。
  • 无论如何,这个答案正中了问题的核心,那就是拥有更多的日期时间选项值得付出微小的速度损失,因为大多数应用程序还有更大的问题在哪里(比如使用臃肿的框架)。正如其他人所说,在查看数据库行时无法看到明确的日期也是开发过程中的失败。
  • 但是,我仍然不相信使用 MySQL 日期时间字段可以使用 MySQL 的内置时间函数进行更好的排序 - 只需使用 time() - ###!速度更快,所有逻辑都放在代码库的一部分中。
  • 我知道有人会引用一些大型 PHP 应用程序。值得注意的是,Facebook 是我们的主要样本。好吧,我需要谈谈你在这里发布的一些观点。首先,我是 IBM 巴西优化工作组的成员,是的,有一些大企业来找我们寻求帮助。其中一家,巴西的大型家具店,做了一个电子商务网站,刚上线就很糟糕。所有应用程序都是基于 PHP 构建的,但没有进行任何测试。他们来到IBM是为了摆脱用户限制。同时350个用户,服务器宕机了。
  • 经过一些规划、测试和重构,站点最终在并发限制下拥有 68000 个用户。好多了。我必须提到的另一点是:尽管 Facebook 将他们的代码保留在 PHP 上,但我认为有理由假设他们的后端不像大多数网站那样简单,无论是基础设施还是编码。你可以打赌他们有一个很好的 CDN、分叉线程、数据库冗余、一致的数据设计、强大的缓存、设计良好的类可以智能地利用资源等等。
【解决方案3】:

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

您可以使用函数 FROM_UNIXTIME 使用 INT 来实现,但您的查询将无法读取。

使用 INT 而不是 DATE 会使您的编程成本比使用 DATE 的成本高出 3 倍。您的安全执行时间不足以支付编程成本。硬件比复杂的编程更便宜。

一旦我们犯了这个错误并将日期保存在 INT 中。半年后,我们决定对大约 30 个站点进行耐火处理,以便于维护。

【讨论】:

    【解决方案4】:

    使用 MySQL 的各种时间和日期格式可以实现使用 Unix 时间戳难以进行的查询。

    一个示例是根据特定周(周数)过滤数据,或者在数据库中添加或删除某个时间范围后使用数据库中的值。

    MySQL 为time and date manipulation 提供了一些很棒的函数,可以很好地处理日期、日期时间和时间格式。

    我们的大多数网站都使用 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 原生的吗?
    • 当然,虽然没有完美的解决方案。 PHP 在 unix time 上运行得非常好,MySQL 在它自己的格式上运行得非常好。在我看来,在两者之间架起一座桥梁是最好的解决方案。我从事的项目完全依赖于 unix 时间,调试数据库问题变得更加困难,并且不支持在 1970 年之前过生日!
    【解决方案5】:

    我喜欢将所有逻辑保存在一个单一的高级域中(即用 php 编写的应用程序)。 MySQL 是一个储存罐——它应该保留。我更喜欢使用诸如http://www.symfony-project.org/plugins/sfDateTime2Plugin 之类的类,然后将 ->dump() 或 ->get() 转换为适当的格式。在应用程序域中编写(和扩展)高级操作比使用静态 mysql 接口更快、更容易。

    PostgreSQL 的界面在 MySQL 上进行了清理。但是我们仍然在这里讨论 MySQL,因为它很流行。这带来了一个重要的考虑。在编写代码或设计系统时,遵守约定通常是有意义的,即使它的计算效率低于其他鲜为人知的选项。这很重要,因为它有利于另一种效率——其他人的可读性。通常,与计算效率低下相比,可读性和可理解性低效率导致的业务费用(和时间)更大。

    不过,我完全赞成尝试 INT。请试一试并写下您的发现。

    干杯

    【讨论】:

      【解决方案6】:

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

      对不起,我应该补充一下,我真的不知道哪个在速度方面更有效,这是您问题的重要部分。

      【讨论】:

        猜你喜欢
        • 2013-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-08
        • 2011-06-20
        • 1970-01-01
        • 2011-10-01
        • 2010-10-02
        相关资源
        最近更新 更多