Are prepared statements cached server-side across multiple page loads with PHP?

后端 未结 7 997
感动是毒
感动是毒 2020-12-09 17:55

I learnt about prepared statements when making a JDBC-enabled Java application, and my app uses a connection pooling layer that assures me that prepared statements are cache

相关标签:
7条回答
  • 2020-12-09 18:04

    When a request is served php "cleans" the instance and frees resources and other variables. This is done in several steps. Since fastcgi keeps the process alive after a request not all steps are executed and not all memory is freed. There is e.g. EG(persistent_list) which is used by mysql_pconnect(), pg_pconnect(), ... This list isn't emptied between requests as long as the process keeps alive (could be, depending on the actual implementation, but that would defy the purpose of EG(persistent_list)). If you use persistent connections your script might get a "re-used" connection established during a previous request.
    To (re-)use a prepared statement directly you need the identifier for that statement (and that connection). When using (php-)postgresql this is simply a (connection-wise) unique string you pass to pg_execute(), so your script has no problem to gain access to the statement previously prepared by another instance (using the same connection).
    Using mysqli or PDO-mysql you need a resource/object as statement identifier. That's kind of a problem since neither the mysqli nor the pdo extension seem to offer a way of storing the resource in EG(persist_list) between requests and you can't recreate it either. Unless php-fpm offers such a "service" it's seems impossible to re-use a mysql prepared statement directly.
    All you can hope for is MySQL's server-side query cache. In recent versions (see link) it may recognize the statement when using prepared statements. But even then it doesn't re-use the actual prepared statement:

    For a prepared statement executed via the binary protocol, comparison with statements in the query cache is based on the text of the statement after expansion of ? parameter markers. The statement is compared only with other cached statements that were executed via the binary protocol. That is, for query cache purposes, statements issued via the binary protocol are distinct from statements issued via the text protocol.

    So, if I'm not mistaken, currently you can't re-use a mysql statement prepared during a previous request in php.

    0 讨论(0)
  • 2020-12-09 18:05

    The only true answer is it depends.

    Prepared statements are finicky beasts when it comes to MySQL. There are a great number of factors that determine whether or not a prepared statement is cached.

    The general idea is if your version is < 5.1.17, the prepared statement is never cached in the query cache, and if using >= 5.1.17, it depends.

    Please see the following page in the MySQL 5.1 manual:

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

    0 讨论(0)
  • 2020-12-09 18:11

    If your PHP application uses connection pooling to the database, and the database caches prepared statements, then yes, the caching will persist between pages. If the prepared statement caching is done by the client library, then this is more nebulous.

    You need to look at the docs for PHP-FPM and/or PDO to see how to tell them to use connection pooling. There should be an option in both to do it.

    You should be aware that MySQL connection setup and teardown is actually very fast and many PHP installations do not use connection pooling because of this. Either way, you should also invest time in your server settings, particularly the wait_timeout parameter. PHP is also designed around the idea that you create everything you need when your pages starts and it all goes away when the page finishes. Most PHP code and libraries assume this is the case. It is quite a different paradigm than under Java.

    0 讨论(0)
  • 2020-12-09 18:12

    You're confusing what is happening at the PHP/Java tier with what's happenning in the database.

    Yes, using prepared statements (usually) means that the execution plan is cached by the database itself (NOT the PHP/Java tier). However it does not follow that this always results in better performance - and an explanation of this would take several hundred pages. However I infer from what you've said elsewhere you are using MySQL as the DBMS which makes the discussion somewhat simpler (IIRC none of the storage engines implement histograms). Typically MySQL will be able to cache enough information about a schema to be able to generate a plan without any disk I/O. OTOH, using prepared statements mean a minimum of three round trips to the DBMS for each query (present statement, present params, retrieve results) while using inlined values eliminates on of these round trips. In the absence of histogram indexes, the value of the variables is irrelevant to the optimal plan detectable by the optimizer.

    The fact that you are using PHP, or PHP-FPM or Java with single or persistent or pooled connections is irrelevant to whether or not prepared-statements are cached/re-used by the DBMS.

    HTH

    C.

    0 讨论(0)
  • 2020-12-09 18:14

    Prepared statements have nothing to do with result caching.

    Result caching can be controlled via db server configuration or forced via memcached and the like.

    I suggest you look into memcached, especially for PHP http://www.php.net/manual/en/book.memcached.php

    0 讨论(0)
  • 2020-12-09 18:15

    you can force mysqli to create a persistent connection by prepending p: to the hostname, as per the php doc: http://www.php.net/manual/en/mysqli.persistconns.php

    However, prepared statements are always closed between page loads, as discussed here: http://dev.mysql.com/doc/refman/5.0/en/apis-php-mysqli.persistconns.html

    Sorry, it can't be done as far as I know. Prepared statements are for a single page load.

    0 讨论(0)
提交回复
热议问题