NOW() 在 PHP 中:处理日期和时间时的优化与性能

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

NOW() 在 PHP 中:你所不知道的时间真相

\n\n

每个 PHP 开发者一生中至少写过一次类似 INSERT INTO logs (created_at) VALUES (NOW()) 的 SQL 查询。这确实很好用。但如果我告诉你,在每个查询中使用 MySQL 函数 NOW() 并不总是最优的呢?如果你的项目处理数百万次查询呢?或者你需要整个脚本使用统一的时间呢?

\n\n

在本文中,我们将探讨如何在 PHP 中模拟 NOW() 函数,如何提高应用程序性能,并避免与时间相关的常见错误。你将了解何时 PHP 版的 NOW() 比直接访问数据库更快,以及时区处理中隐藏着哪些陷阱。

\n\n
\n\n

1. 什么是 NOW() 以及为何要在 PHP 中模拟它?

\n\n

NOW() 是 MySQL(及其他数据库管理系统)的内置函数,返回当前日期和时间,格式为 YYYY-MM-DD HH:MM:SS。看起来似乎没必要改变什么?但有一些细节需要注意:

\n\n
    \n
  • 数据库负载:每次调用 NOW() 都是一次独立的数据库请求。如果你要插入 10,000 行数据,就需要发送 10,000 次请求、接收响应,然后才能插入数据。
  • \n
  • 时间不一致:如果你的脚本运行几秒钟,不同查询中的 NOW() 可能返回不同的时间(虽然差异可能只有毫秒,但对于日志来说至关重要)。
  • \n
  • 可移植性:切换数据库管理系统(例如改用 PostgreSQL 或 SQLite)时,NOW() 可能无法工作或行为不同。
  • \n
\n\n

解决方案:在 PHP 端计算时间,并将其作为参数传递。这样,你可以在所有操作中使用统一的时间,降低数据库负载,并使代码更具通用性。

\n\n
\n\n

2. 如何在 PHP 中实现 NOW():三种经过验证的方法

\n\n

2.1. 经典方法 date('Y-m-d H:i:s')

\n\n

最简单、最快的方法是使用内置函数 date():

\n\n
<?php\n$now = date('Y-m-d H:i:s');\necho $now; // 2025-01-15 14:30:00\n?>
\n\n

优点:随处可用,内存消耗最小,无需加载额外类。
\n缺点:依赖于 php.ini 中设置的时区(date.timezone)。

\n\n

2.2. 面向对象方法 DateTime

\n\n

PHP 的现代标准是 DateTime 类。它更灵活、更方便:

\n\n
<?php\n$now = new DateTime();\necho $now->format('Y-m-d H:i:s'); // 2025-01-15 14:30:00\n?>
\n\n

你可以显式指定时区:

\n\n
<?php\n$timezone = new DateTimeZone('Europe/Moscow');\n$now = new DateTime('now', $timezone);\necho $now->format('Y-m-d H:i:s'); // 2025-01-15 17:30:00 (MSK)\n?>
\n\n

2.3. 使用 DateTimeImmutable 处理微秒

\n\n

对于精确测量或需要高精度日志的情况,请使用 DateTimeImmutable(不会修改原始对象):

\n\n
<?php\n$now = new DateTimeImmutable();\necho $now->format('Y-m-d H:i:s.u'); // 2025-01-15 14:30:00.123456\n?>
\n\n

建议:如果你只需要时间用于数据库插入,请使用 date()——它比 DateTime 快 10-15%。

\n\n
\n\n

3. 性能优化:测试与比较

\n\n

让我们做一个简单的基准测试。比较在 100,000 次迭代循环中获取当前时间的三种方法:

\n\n
<?php\n$iterations = 100000;\n\n// 方法 1:date()\n$start = microtime(true);\nfor ($i = 0; $i < $iterations; $i++) {\n    $now = date('Y-m-d H:i:s');\n}\n$time1 = microtime(true) - $start;\n\n// 方法 2:DateTime\n$start = microtime(true);\nfor ($i = 0; $i < $itera                

博客

书籍推荐