2012-11-26 84 views
9

PDO是否应准备使用之后的语句被释放?如果是这样,怎么样?具体而言,我正在询问关于MySQL的内容 - 你应该怎样,并且应该通过PDO调用DEALLOCATE PREPARE。 (编辑:为了澄清,这个问题是不是指模拟准备,但真正的准备。)腾出PDO预处理语句(DEALLOCATE PREPARE)

而且 - 将这个免费(大时)设置的结果吗?

说明:

我已经沿着

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

这使我想知道这是什么一样,何时,如果f unset($stmnt);将是不同的线条看到代码?

手动指示

当制备查询时,数据库将分析,编译和 优化其计划用于执行所述查询。 [...]通过使用准备好的 声明,应用程序避免重复分析/编译/优化循环。

它倾向于暗示你应该不分配语句,并且MySQL有能力。所以,

  1. 你能打电话DEALLOCATE PREPARE,以及如何
  2. 你应该这样做?
  3. 而且任何人都可以证实,设置声明为null(或注销的语句)会做一样的“free_result”为mysql_和mysqli_?
  4. 它立即发生,还是等垃圾收集器踢?

对于完整性,另一SO question提到“free_result”和mysqli_()“关闭”功能表明,释放的声明实际上增加了时间(除非你有大量的内存使用情况和需要的空间)。但是“free_result”与释放SQL服务器使缓存准备好的语句不同。

+0

你是否特意关闭模拟准备?默认情况下,准备好的语句在驱动程序中进行模拟,并在请求结束时释放(当所有内容都是GCd时)。无论如何故意放开它们的意义何在?通过在可能的情况下重新使用预先准备好的语句来提高性能。为了解决第3点,当语句被销毁时调用[free_result](http://lxr.php.net/xref/PHP_5_4/ext/pdo_mysql/mysql_statement.c#55)(未设置,请求结束等)没有测试,我相信立即调用dtors。 – Leigh

+0

是的,我不是在模仿准备 - 抱歉,应该在问题中明确表达(但否则问题是毫无意义的)。为什么释放他们?因为有几个单独调用的语句不再用于该连接 - 所以它们也可以被释放(优化不被缓存)。那些被重复使用的东西我会坚持(直到不再需要,那么同样的问题适用于如何释放它们)。 – Robbie

回答

3

应该PDO使用后准备的语句被释放?如果是这样,怎么样?

在MySQL的情况下?没有为什么?

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

虽然你可以把它打开,你还不需要明确关闭,除非您还使用unbuffered queries手柄。仅仅让语句句柄超出范围或将其设置为空将而不是关闭游标。如果您使用的是未缓冲的查询,则此仅限于。如果你不是,那么让它超出范围或将其设置为空就足以完全关闭手柄。您还链接到DEALLOCATE PREPARE。该语法只有需要手动使用SQL字符串调用PREPARE。这与MySQL C-level API-based prepared statements完全和完全分开,这是PDO_MYSQL正在使用的操作。 (好的,也许你正在使用mysqlnd,但实际上它是一样的。)

+0

对不起 - 我应该澄清,我指的是使用真实准备的语句。我找不到源代码,但是我记得读过调用“prepare()”的时候会调用“PREAPRE”到数据库 - 这导致我应该调用DEALLOCATE PREPARE的问题。我将测试PREPARE未被调用,因为您声称 - 我已将所有查询记录在工作中,所以我会回复你)。我不缓冲查询。感谢回复 - 我会在一天后跟进。 – Robbie

+0

如果您在处理C代码(和mysqlnd)使用的线级API时在任何地方都能看到实际的'PREPARE' SQL *,我会吃一顶帽子。那会是如此... *错误* ...我的思想将被吹倒*周*关于它是多么的错误。 – Charles

+2

没有要求吃的帽子 - 我只是检查了日志,而且完全如您所述。 PREPARE没有出现,但是对prepare()的调用确实符合您链接的C级API。和mysql_stmt_close(stmt))似乎也立即被调用,大概是在PHP中将stmnt设置为“null”(显然是有限的测试,但在日志中总是出现“stmt close”)。感谢指点 - 我会东部休息,我做对了。 – Robbie

0

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

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

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

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

+0

这个问题不是关于pdo陈述,而是关于准备陈述。尽管为了节省您的20MB,您应该使用无缓冲的查询 –