一尘不染

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

mysql

我在制作启用JDBC的Java应用程序时了解了预备语句,并且我的应用程序使用连接池层,这确保了预备语句在服务器端缓存,这带来了性能上的好处。

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

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

  1. 将PHP-FPM与mysqli或PDO一起使用是否会使连接的时间长于单个页面加载的时间?
  2. 如果没有,我可以做到吗?
  3. 如果可以,或者我执行了#2,这将使准备好的语句的缓存持续的时间长于一页加载的时间吗?

编辑:

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


阅读 218

收藏
2020-05-17

共1个答案

一尘不染

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

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

因此,如果我没记错的话,当前您将无法重新使用在php中先前请求期间准备的mysql语句。

2020-05-17