使用PHP在多个页面加载的服务器端缓存预准备语句吗?

时间:2010-01-11 01:25:54

标签: php mysql

我在创建支持JDBC的Java应用程序时学习了预处理语句,而我的应用程序使用连接池层来确保预准备语句在服务器端缓存,这样可以带来性能优势。

但是,对于PHP,我读过的所有内容都表明它们仅在页面加载的生命周期中被缓存。通常我不会多次重复相同的查询,但是在给定的页面加载上运行几个不同的查询,但会在多个页面加载中重复它们。

由于我的PHP进程是持久的(即它们将在其生命周期中服务数百个页面而不是仅使用PHP-FPM),我想知道它们是否会重新使用数据库连接,而不是产生并将其终止每次击中。

  1. 将PHP-FPM与mysqli或PDO结合使用会比单页加载更长时间吗?
  2. 如果没有,我可以制作吗?
  3. 如果确实如此,或者我做#2,这是否会持续缓存预备语句而不仅仅是一页加载?
  4. 编辑:

    只是为了澄清,我不是在谈论查询缓存,它完全是另一个野兽,或者缓存查询的输出。我想缓存已编译的预准备语句及其执行计划服务器端。

7 个答案:

答案 0 :(得分:12)

当提供请求时,php“清理”实例并释放资源和其他变量。这是通过几个步骤完成的。由于fastcgi在请求之后保持进程处于活动状态,并非所有步骤都被执行,并且并未释放所有内存。例如有由mysql_pconnect()pg_pconnect()使用的EG(persistent_list),...只要进程保持活动状态,这个列表就不会在请求之间清空(可能是,取决于实际的实现,但是会违背EG(persistent_list)的目的。如果使用持久连接,则脚本可能会在先前的请求中建立“重用”连接 要(重新)直接使用预准备语句,您需要该语句的标识符(以及该连接)。当使用(php-)postgresql时,这只是一个传递给pg_execute()的(连接方式)唯一字符串,所以你的脚本没有问题可以访问之前由另一个实例准备的语句(使用相同的连接) 。
使用mysqliPDO-mysql,您需要一个资源/对象作为语句标识符。这是一个问题,因为mysqli和pdo扩展似乎都没有提供在请求之间将资源存储在EG(persist_list)中的方法,您也无法重新创建它。除非php-fpm提供这样的“服务”,否则直接重用mysql准备语句似乎是不可能的 所有你能想到的是MySQL的server-side query cache。在最近的版本中(参见链接),它可以在使用预准备语句时识别语句。但即便如此,它也不会重复使用实际准备好的声明:

对于通过二进制协议执行的预处理语句,与查询缓存中的语句进行比较是基于扩展后的语句文本?参数标记。该语句仅与通过二进制协议执行的其他缓存语句进行比较。也就是说,对于查询缓存目的,通过二进制协议发出的语句与通过文本协议发出的语句不同。

所以,如果我没弄错的话,目前你不能重新使用在php中的先前请求中准备的mysql语句。

答案 1 :(得分:4)

您在PHP / Java层发生的事情与数据库中发生的事情相混淆。

是的,使用预准备语句(通常)意味着执行计划由数据库本身(而不是PHP / Java层)缓存。然而,并不是说这总是会带来更好的性能 - 对此的解释将需要数百页。但是,我从你在其他地方所说的内容中推断出你使用MySQL作为DBMS,这使讨论更简单(IIRC没有任何存储引擎实现直方图)。通常,MySQL将能够缓存有关模式的足够信息,以便能够生成没有任何磁盘I / O的计划。 OTOH,使用预准备语句意味着每次查询至少三次往返DBMS(当前语句,当前参数,检索结果),而使用内联值可以消除这些往返行程。在没有直方图索引的情况下,变量的值与优化程序可检测的最佳计划无关。

您使用PHP或PHP-FPM或Java与单个或持久或池化连接这一事实与DBMS是否缓存/重用预备语句无关。

HTH

下进行。

答案 2 :(得分:2)

如果您的PHP应用程序使用连接池到数据库,并且数据库缓存预准备语句,那么是,缓存将在页面之间保持不变。如果准备好的语句缓存是由客户端库完成的,那么这就更模糊了。

您需要查看PHP-FPM和/或PDO的文档,了解如何告诉他们使用连接池。两者都应该有选择。

您应该知道MySQL连接设置和拆卸实际上非常快,并且许多PHP安装因此而不使用连接池。无论哪种方式,您还应该在服务器设置上投入时间,尤其是wait_timeout参数。 PHP的设计也是为了在页面启动时创建所需的一切,并在页面完成时消失。大多数PHP代码和库都假设是这种情况。这是一种与Java不同的范式。

答案 3 :(得分:2)

唯一真正的答案是取决于

准备好的语句对于MySQL来说是挑剔的野兽。有许多因素决定了是否缓存了预准备语句。

一般的想法是你的版本是< 5.1.17,准备好的语句永远缓存在查询缓存中,如果使用> = 5.1.17,依赖

请参阅MySQL 5.1手册中的以下页面:

http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html

答案 4 :(得分:2)

根据php doc:http://www.php.net/manual/en/mysqli.persistconns.php

,您可以强制mysqli通过将p:添加到主机名来创建持久连接

但是,准备好的语句总是在页面加载之间关闭,如下所述:http://dev.mysql.com/doc/refman/5.0/en/apis-php-mysqli.persistconns.html

抱歉,据我所知,这是无法做到的。准备好的语句适用于单页加载。

答案 5 :(得分:-1)

预备语句与结果缓存无关。

结果缓存可以通过数据库服务器配置控制,也可以通过memcached等强制执行。

我建议您查看memcached,尤其是PHP http://www.php.net/manual/en/book.memcached.php

答案 6 :(得分:-1)

在大多数情况下,PHP不会缓存查询或查询结果。无论是什么线程或连接发出查询,MySQL都会执行这种缓存。

如果您希望跨多个页面加载或多个服务器进行服务器端缓存,则使用MySQL查询缓存和服务器端缓存(APC,基于文件的缓存,memcached等)。