Quickstart: how to cache selected queries based on a pattern

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@322215 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Ulf Wendel 2012-01-13 18:55:52 +00:00
parent 0d604bbc9d
commit 8244b37fb3
3 changed files with 268 additions and 2 deletions

View file

@ -415,8 +415,8 @@
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<example>
@ -503,7 +503,6 @@ array(4) {
]]>
</screen>
</example>
</refsect1>

View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 322131 $ -->
<refentry xml:id="function.mysqlnd-qc-set-is-select" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<refnamediv>
<refname>mysqlnd_qc_set_is_select</refname>
<refpurpose>Installs a callback which decides whether a statement is cached</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<type>mixed</type>
<methodname>mysqlnd_qc_set_is_select</methodname>
<methodparam>
<type>string</type>
<parameter>callback</parameter>
</methodparam>
</methodsynopsis>
<para>
Installs a callback which decides whether a statement is cached.
</para>
<para>
There are several ways of hinting PELC/mysqlnd_qc to cache a query.
By default, PECL/mysqlnd_qc attempts to cache a if caching of all statements
is enabled or the query string begins with a certain SQL hint.
The plugin internally calls a function named <literal>is_select()</literal>
to find out. This internal function can be replaced with a user-defined callback.
Then, the user-defined callback is responsible to decide whether the plugin
attempts to cache a statement. Because the internal function is replaced
with the callback, the callback gains full control. The callback is free
to ignore the configuration setting <literal>mysqlnd_qc.cache_by_default</literal>
and SQL hints.
</para>
<para>
The callback is invoked for every statement inspected by the plugin.
It is given the statements string as a parameter. The callback returns
&false; if the statement shall not be cached. It returns &true; to
make the plugin attempt to cache the statements result set, if any.
A so-created cache entry is given the default TTL set with the
PHP configuration directive <literal>mysqlnd_qc.ttl</literal>.
If a different TTL shall be used, the callback returns a numeric
value to be used as the TTL.
</para>
<para>
The internal <literal>is_select</literal> function is part of the internal
cache storage handler interface. Thus, a user-defined storage handler
offers the same capabilities.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
&no.function.parameters;
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
&return.success;
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<example>
<para>
</para>
<programlisting role="php">
<![CDATA[
<?php
/* callback which decides if query is cached */
function is_select($query) {
static $patterns = array(
/* true - use default from mysqlnd_qc.ttl */
"@SELECT\s+.*\s+FROM\s+test@ismU" => true,
/* 3 - use TTL = 3 seconds */
"@SELECT\s+.*\s+FROM\s+news@ismU" => 3
);
/* check if query does match pattern */
foreach ($patterns as $pattern => $ttl) {
if (preg_match($pattern, $query)) {
printf("is_select(%45s): cache\n", $query);
return $ttl;
}
}
printf("is_select(%45s): do not cache\n", $query);
return false;
}
mysqlnd_qc_set_is_select("is_select");
/* Connect, create and populate test table */
$mysqli = new mysqli("host", "user", "password", "schema");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* cache put */
$mysqli->query("SELECT id FROM test WHERE id = 1");
/* cache hit */
$mysqli->query("SELECT id FROM test WHERE id = 1");
/* cache put */
$mysqli->query("SELECT * FROM test");
?>
]]>
</programlisting>
&examples.outputs;
<screen>
<![CDATA[
is_select( DROP TABLE IF EXISTS test): do not cache
is_select( CREATE TABLE test(id INT)): do not cache
is_select( INSERT INTO test(id) VALUES (1), (2), (3)): do not cache
is_select( SELECT id FROM test WHERE id = 1): cache
is_select( SELECT id FROM test WHERE id = 1): cache
is_select( SELECT * FROM test): cache
]]>
</screen>
</example>
</refsect1>
<refsect1 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member>
<link linkend="mysqlnd-qc.configuration">Runtime configuration</link>
</member>
<member>
<link linkend="ini.mysqlnd-qc.ttl">mysqlnd_qc.ttl</link>
</member>
<member>
<link linkend="ini.mysqlnd-qc.cache-by-default">mysqlnd_qc.cache_by_default</link>
</member>
<member>
<function>mysqlnd_qc_set_user_handlers</function>
</member>
</simplelist>
</para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

View file

@ -661,6 +661,110 @@ Script runtime : 3 seconds
</para>
</section>
<section xml:id="mysqlnd-qc.pattern_based_caching" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Pattern based caching</title>
<para>
An application has three options for telling PECL/mysqlnd_qc whether a particular
statement shall be used. The most basic approach is to cache all statements by
setting <literal><link linkend="mysqlnd-qc.configuration">
mysqlnd_qc.cache_by_default = 1</link></literal>. This apporach is often of little
practical value. But it enables users to make a quick estimation about
the maximum performance gains from caching. An application designed to
use a cache may able to prefix selected statements with the appropriate SQL
hints. However, altering an applications source code may not always be possible
or desired, for example, to avoid problems with software updates. Therefore,
PECL/mysqlnd_qc allows setting a callback which decides if a query is to be
cached.
</para>
<para>
The callback is installed with the <function>mysqlnd_qc_set_is_select</function>
function. The callback is given the statement string of every statement
inspected by the plugin. Then, the callback can decide whether to cache
the function. The callback is supposed to return <literal>FALSE</literal>
if the statement shall not be cached. A return value of <literal>TRUE</literal>
makes the plugin try to add the statement into the cache. The cache entry
will be given the default TTL (<literal><link linkend="mysqlnd-qc.configuration">
mysqlnd_qc.ttl</link></literal>). If the callback returns
a numberical value it is used as the TTL instead of the global default.
</para>
<para>
<example>
<programlisting role="ini">
<![CDATA[
mysqlnd_qc.enable_qc=1
mysqlnd_qc.collect_statistics=1
]]>
</programlisting>
<programlisting role="php">
<![CDATA[
<?php
/* callback which decides if query is cached */
function is_select($query) {
static $patterns = array(
/* true - use default from mysqlnd_qc.ttl */
"@SELECT\s+.*\s+FROM\s+test@ismU" => true,
/* 3 - use TTL = 3 seconds */
"@SELECT\s+.*\s+FROM\s+news@ismU" => 3
);
/* check if query does match pattern */
foreach ($patterns as $pattern => $ttl) {
if (preg_match($pattern, $query)) {
printf("is_select(%45s): cache\n", $query);
return $ttl;
}
}
printf("is_select(%45s): do not cache\n", $query);
return false;
}
/* install callback */
mysqlnd_qc_set_is_select("is_select");
/* Connect, create and populate test table */
$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* cache put */
$mysqli->query("SELECT id FROM test WHERE id = 1");
/* cache hit */
$mysqli->query("SELECT id FROM test WHERE id = 1");
/* cache put */
$mysqli->query("SELECT * FROM test");
$stats = mysqlnd_qc_get_core_stats();
printf("Cache put: %d\n", $stats['cache_put']);
printf("Cache hit: %d\n", $stats['cache_hit']);
?>
]]>
</programlisting>
&examples.outputs;
<screen>
<![CDATA[
is_select( DROP TABLE IF EXISTS test): do not cache
is_select( CREATE TABLE test(id INT)): do not cache
is_select( INSERT INTO test(id) VALUES (1), (2), (3)): do not cache
is_select( SELECT id FROM test WHERE id = 1): cache
is_select( SELECT id FROM test WHERE id = 1): cache
is_select( SELECT * FROM test): cache
Cache put: 2
Cache hit: 1
]]>
</screen>
</example>
</para>
<para>
The examples callback tests if a statement string matches a pattern.
If this is the case, it either returns <literal>TRUE</literal> to cache
the statement using the global default TTL or an alternative TTL.
</para>
<para>
To minimize application changes the callback can put into and registered
in an auto prepend file.
</para>
</section>
<section xml:id="mysqlnd-qc.slam-defense" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Slam defense</title>
<para>