代码之家  ›  专栏  ›  技术社区  ›  ZoFreX mxk

准备好的语句是否使用PHP跨多个页面加载缓存到服务器端?

  •  14
  • ZoFreX mxk  · 技术社区  · 16 年前

    在制作支持JDBC的Java应用程序时,我了解了准备好的语句,我的应用程序使用了连接池层,确保准备好的语句被缓存在服务器端,从而提高了性能。

    由于我的PHP进程是持久性的(也就是说,它们将在其生命周期中提供数百个页面,而不是使用PHP-FPM提供一个页面),我想知道它们是否会重复使用数据库连接,而不是在每次点击时生成并杀死它们。

    1. 将PHP-FPM与mysqli或PDO结合使用会使连接保持比单个页面加载更长的时间吗?
    2. 如果是这样的话,或者我是这样做的#2,那么准备好的语句的缓存会比一个页面加载时间更长吗?

    编辑:

    7 回复  |  直到 16 年前
        1
  •  12
  •   VolkerK    16 年前

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

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

        2
  •  4
  •   symcbean    16 年前

    您混淆了PHP/Java层上发生的事情和数据库中发生的事情。

    是的,使用准备好的语句(通常)意味着执行计划由数据库本身(而不是PHP/Java层)缓存。然而,这并不意味着这总是能带来更好的性能——对此的解释需要几百页的篇幅。但是,我从您在其他地方说过的话推断,您正在使用MySQL作为DBMS,这使得讨论更加简单(IIRC没有一个存储引擎实现直方图)。通常,MySQL能够缓存足够多的模式信息,以便在没有任何磁盘I/O的情况下生成计划。OTOH,使用prepared语句意味着每个查询(present语句、present参数、retrieve结果)到DBMS的最少三次往返,而使用内联值则消除了其中的一次往返。在没有直方图索引的情况下,变量的值与优化器检测到的最优计划无关。

    使用PHP、PHP-FPM或Java进行单连接、持久连接或池连接的事实与DBMS是否缓存/重用准备好的语句无关。

    嗯

    C

        3
  •  2
  •   staticsan    16 年前

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

    您应该知道,MySQL连接设置和拆卸实际上非常快,因此许多PHP安装不使用连接池。无论哪种方式,您都应该在服务器设置上投入时间,特别是 wait_timeout

        4
  •  2
  •   hobodave    16 年前

    唯一正确的答案是 视情况而定 .

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

    从未 缓存在查询缓存中,如果使用>=5.1.17, 视情况而定 .

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

        5
  •  2
  •   Xosofox    10 年前

    您可以通过在主机名前加上p:来强制mysqli创建持久连接,如php文档所示: http://www.php.net/manual/en/mysqli.persistconns.php

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

    对不起,据我所知,这件事办不到。准备好的语句用于单页加载。

        6
  •  -1
  •   Horia Dragomir    16 年前

    准备好的语句与结果缓存无关。

    我建议你调查一下 memcached ,尤其是PHP http://www.php.net/manual/en/book.memcached.php

        7
  •  -1
  •   gabrielk    16 年前

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