【问题标题】:Freeing up PDO prepared statements (DEALLOCATE PREPARE)释放 PDO 准备好的语句 (DEALLOCATE PREPARE)
【发布时间】:2012-11-13 14:22:07
【问题描述】:

是否应该在使用后释放 PDO 准备好的语句?如果是这样,怎么办?具体来说,我问的是 MySQL - 你怎么能,你应该如何通过 PDO 致电DEALLOCATE PREPARE。 (编辑:澄清一下,这个问题不是指模拟的准备,而是真正的准备。)

另外 - 这是否会释放结果集(如果很大)?

解释:

我见过类似

的代码
$stmnt = $db->prepare($sql);
$stmnt->execute($aParams);
$stmnt = null;

这让我想知道这是做什么的,什么时候,如果 f unset($stmnt); 会有所不同?

说明书上注明

当查询准备好后,数据库将分析、编译和 优化其执行查询的计划。 [...] 通过使用准备好的 声明应用程序避免重复 分析/编译/优化周期。

这倾向于建议您应该取消分配语句,而 MySQL 具有此功能。所以,

  1. 你能打电话给DEALLOCATE PREPARE吗,怎么打
  2. 你应该这样做吗?
  3. 任何人都可以确认将语句设置为 null(或取消设置语句)将与 mysql_ 和 mysqli_ 的“free_result”相同吗?
  4. 是立即发生,还是等待垃圾收集器启动?

为了完整起见,另一个SO question 指的是mysqli_() 的“free_result”和“close”函数,这表明释放语句实际上会增加时间(除非您有大量内存使用并需要空间)。但是“free_result”不同于将 SQL 服务器从准备好的语句缓存中释放出来。

【问题讨论】:

  • 你是不是专门关掉了仿真准备?默认情况下,准备好的语句在驱动程序中模拟,并在请求结束时被释放(当一切都是 GCd 时)。无论如何,故意释放他们有什么意义?通过在可能的情况下重用准备好的语句来提高性能。为了解决第 3 点,free_result is called when a statement is destroyed(未设置、请求结束等) - 未经测试,我相信 dtor 会立即被调用。
  • 是的,我没有模仿准备 - 抱歉,应该在问题中明确说明(但否则问题毫无意义)。为什么要释放他们?因为有几个单独调用的语句不再用于该连接 - 所以它们也可以被释放(优化不被缓存)。那些确实被重复使用的我会保留(直到不再需要,然后同样的问题适用于如何释放它们)。

标签: php mysql pdo prepared-statement


【解决方案1】:

是否应该在使用后释放 PDO 准备好的语句?如果有,怎么做?

在 MySQL 的上下文中?不。为什么?

PDO emulates prepared statements by default。这意味着 PDO 本身会执行参数替换、转义等操作,并将 SQL 块向下发送,而不是使用 native 准备好的语句。

虽然您可以打开它,但您仍然不需要明确关闭句柄除非您也在使用unbuffered queries。仅仅让语句句柄超出范围或将其设置为 null 将不会关闭游标。同样,这在您使用无缓冲查询时很重要。如果不是,那么让它超出范围或将其设置为 null 就足以干净地关闭句柄。

您还链接到DEALLOCATE PREPARE手动使用 SQL 字符串调用PREPARE 时需要该语法。这是一个完全独立于MySQL C-level API-based prepared statements 的操作,PDO_MYSQL 正在使用它。 (好吧,也许您使用的是mysqlnd,但实际上是同一回事。)

【讨论】:

  • 对不起 - 我应该澄清一下,我指的是使用真正的准备好的语句。我找不到源,但我记得读过调用“prepare()”确实会调用数据库的“PREAPRE”——这导致了我是否应该调用 DEALLOCATE PREPARE 的问题。我将测试 PREPARE 是否没有像您声称的那样被调用 - 我在工作中记录了所有查询,所以我会回复您)。我没有缓冲查询。感谢您的回复 - 我会在一天后跟进。
  • 如果您在处理 C 代码(和 mysqlnd)使用的线级 API 时看到实际的PREPARE SQL anywhere,我会吃帽子。那太...... ...我会在几个星期的时间里惊慌失措地想这是多么的错误。
  • 不需要吃帽子 - 我刚刚检查了日志,它与您描述的完全一样。 PREPARE 不会出现,但对 prepare() 的调用会出现 - 适合您链接的 C 级 API。并且 mysql_stmt_close(stmt)) 似乎也立即被调用,大概是在 PHP 中将 stmnt 设置为“null”时(显然是有限的测试,但“stmt close”总是在日志中跟随)。感谢您的指点 - 我会在东部休息,我做得对。
【解决方案2】:

是的。完成准备语句后,您可以将其设置为 NULL 或使用 unset()

对于具有多个查询和大型数据库的脚本,这会有所不同。您可以使用以下方法进行测试:

$before = memory_get_usage();
$stmt = NULL;
die(memory_get_usage() - $before);

对我来说,这节省了 20MB 的内存,但后来导致脚本崩溃。

【讨论】:

  • 问题不是关于 pdo 语句,而是关于准备好的语句。虽然要节省 20MB,但您应该一直使用无缓冲查询
  • 这是相关的 PDOStatement 是一个准备好的语句,也是一个结果集。也许将这些语言分开会更优雅。无缓冲查询引入了额外的设计约束。具体来说,您可能没有在一个连接上打开多个活动的无缓冲查询,这在我的应用程序中是一个不可接受的约束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 2023-03-19
  • 2011-07-13
  • 2017-09-29
相关资源
最近更新 更多