CS and WS

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@324476 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
Philip Olson 2012-03-22 23:50:17 +00:00
parent 8a08005bc7
commit c4e357af9a
3 changed files with 187 additions and 196 deletions

View file

@ -58,21 +58,18 @@ MYSQLND_QC_TTL_SWITCH: qc_ttl=
<varlistentry xml:id="constant.mysqlnd-qc-enable-switch">
<term>
<constant>MYSQLND_QC_ENABLE_SWITCH</constant>
(
<type>string</type>)
(<type>string</type>)
</term>
<listitem>
<simpara>
SQL hint used to enable caching of a query.
SQL hint used to enable caching of a query.
</simpara>
</listitem>
</varlistentry>
<varlistentry xml:id="constant.mysqlnd-qc-disable-switch">
<term>
<constant>MYSQLND_QC_DISABLE_SWITCH</constant>
(
<type>string</type>)
(<type>string</type>)
</term>
<listitem>
<simpara>
@ -84,8 +81,7 @@ MYSQLND_QC_TTL_SWITCH: qc_ttl=
<varlistentry xml:id="constant.mysqlnd-qc-ttl-switch">
<term>
<constant>MYSQLND_QC_TTL_SWITCH</constant>
(
<type>string</type>)
(<type>string</type>)
</term>
<listitem>
<simpara>
@ -96,8 +92,7 @@ MYSQLND_QC_TTL_SWITCH: qc_ttl=
<varlistentry xml:id="constant.mysqlnd-qc-server-id">
<term>
<constant>MYSQLND_QC_SERVER_ID_SWITCH</constant>
(
<type>string</type>)
(<type>string</type>)
</term>
<listitem>
<simpara>
@ -129,7 +124,6 @@ MYSQLND_QC_TTL_SWITCH: qc_ttl=
</varlistentry>
</variablelist>
</para>
<para>
<emphasis role="bold"><function>mysqlnd_qc_set_cache_condition</function> related</emphasis>
</para>
@ -167,13 +161,12 @@ $pdo_mysql->query("SELECT id, title FROM news");
<varlistentry xml:id="constant.mysqlnd-qc-condition-meta-schema-pattern">
<term>
<constant>MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN</constant>
(
<type>int</type>)
(<type>int</type>)
</term>
<listitem>
<simpara>
Used as a parameter of <function>mysqlnd_qc_set_cache_condition</function>
to set conditions for schema based automatic caching.
Used as a parameter of <function>mysqlnd_qc_set_cache_condition</function>
to set conditions for schema based automatic caching.
</simpara>
</listitem>
</varlistentry>

View file

@ -423,8 +423,7 @@
<listitem>
<para>
<literal>sqlite</literal> storage handler: data file. Any setting
but
<literal>:memory:</literal> may be of little practical value.
but <literal>:memory:</literal> may be of little practical value.
</para>
</listitem>
</varlistentry>

View file

@ -42,7 +42,7 @@
a comparison with proxy based solutions.
</para>
<para>
<emphasis role="bold">Transparent to use</emphasis>
<emphasis role="bold">Transparent to use</emphasis>
</para>
<para>
At PHP run time PECL/mysqlnd_qc can proxy queries send from PHP
@ -61,7 +61,7 @@
PHP MySQL extensions.
</para>
<para>
<emphasis role="bold">Flexible storage: various storage handler</emphasis>
<emphasis role="bold">Flexible storage: various storage handler</emphasis>
</para>
<para>
Various storage handler are supported to offer different scopes for cache
@ -105,8 +105,8 @@
However, it is recommended to pick one storage handler and use it for all cache entries.
</para>
<para>
<emphasis role="bold">Built-in slam defense to avoid overloading</emphasis>
</para>
<emphasis role="bold">Built-in slam defense to avoid overloading</emphasis>
</para>
<para>
To avoid overload situations the cache plugin has a built-in slam defense mechanism.
If a popular cache entries expires many clients using the cache entries will try
@ -124,8 +124,8 @@
situation.
</para>
<para>
<emphasis role="bold">Unique approach to caching</emphasis>
</para>
<emphasis role="bold">Unique approach to caching</emphasis>
</para>
<para>
PECL/mysqlnd_qc has a unique approach to caching result sets that is superior
to application based cache solutions. Application based solutions first fetch
@ -183,7 +183,7 @@ mysqlnd_qc.enable_qc=1
</listitem>
<listitem>
<simpara>
User supplied callbacks to decide on a per query basis, for example, using <function>mysqlnd_qc_is_select</function>
User supplied callbacks to decide on a per query basis, for example, using <function>mysqlnd_qc_is_select</function>
</simpara>
</listitem>
<listitem>
@ -221,7 +221,7 @@ mysqlnd_qc.enable_qc=1
</para>
<para>
<itemizedlist>
<listitem>
<listitem>
<para>
not eligible for caching and not cached: <literal>INSERT INTO test(id) VALUES (1)</literal>
</para>
@ -267,21 +267,25 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2)");
/* Will be cached because of the SQL hint */
$start = microtime(true);
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Total time uncached query: %.6fs\n", microtime(true) - $start);
/* Cache hit */
$start = microtime(true);
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Total time cached query: %.6fs\n", microtime(true) - $start);
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(1) {
@ -360,7 +364,7 @@ $res->free();
?>
]]>
</programlisting>
&examples.outputs;
&examples.outputs;
<screen>
<![CDATA[
array(1) {
@ -402,24 +406,24 @@ $mysqli->query("INSERT INTO test(id) VALUES (1)");
for ($i = 0; $i < 3; $i++) {
$start = microtime(true);
$start = microtime(true);
/* Note: statement will not be cached because of NOW() use */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$row = $res->fetch_assoc();
/* Note: statement will not be cached because of NOW() use */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$row = $res->fetch_assoc();
/* dump results */
var_dump($row);
/* dump results */
var_dump($row);
printf("Total time: %.6fs\n", microtime(true) - $start);
printf("Total time: %.6fs\n", microtime(true) - $start);
/* pause one second */
sleep(1);
/* pause one second */
sleep(1);
}
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(2) {
@ -475,24 +479,24 @@ $mysqli->query("INSERT INTO test(id) VALUES (1)");
for ($i = 0; $i < 3; $i++) {
$start = microtime(true);
$start = microtime(true);
/* Note: statement will not be cached because of NOW() use */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$row = $res->fetch_assoc();
/* Note: statement will not be cached because of NOW() use */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$row = $res->fetch_assoc();
/* dump results */
var_dump($row);
/* dump results */
var_dump($row);
printf("Total time: %.6fs\n", microtime(true) - $start);
printf("Total time: %.6fs\n", microtime(true) - $start);
/* pause one second */
sleep(1);
/* pause one second */
sleep(1);
}
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(2) {
@ -573,30 +577,30 @@ $mysqli->query("CREATE TABLE test(id VARCHAR(255))");
for ($i = 0; $i < 7; $i++) {
/* update DB row */
if (!$mysqli->query("DELETE FROM test") ||
!$mysqli->query("INSERT INTO test(id) VALUES (NOW())"))
/* Of course, a real-life script should do better error handling */
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* update DB row */
if (!$mysqli->query("DELETE FROM test") ||
!$mysqli->query("INSERT INTO test(id) VALUES (NOW())"))
/* Of course, a real-life script should do better error handling */
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* select latest row but cache results */
$query = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/";
$query .= "SELECT id AS _time FROM test";
if (!($res = $mysqli->query($query)) ||
!($row = $res->fetch_assoc()))
{
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
}
$res->free();
printf("Wall time %s - DB row time %s\n", date("H:i:s"), $row['_time']);
/* select latest row but cache results */
$query = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/";
$query .= "SELECT id AS _time FROM test";
if (!($res = $mysqli->query($query)) ||
!($row = $res->fetch_assoc()))
{
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
}
$res->free();
printf("Wall time %s - DB row time %s\n", date("H:i:s"), $row['_time']);
/* pause one second */
sleep(1);
/* pause one second */
sleep(1);
}
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
Wall time 14:55:59 - DB row time 2012-01-11 14:55:59
@ -644,11 +648,9 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2)");
printf("Default TTL\t: %d seconds\n", ini_get("mysqlnd_qc.ttl"));
/* Will be cached for 2 seconds */
$sql = sprintf("/*%s*//*%s%d*/SELECT id FROM test WHERE id = 1",
MYSQLND_QC_ENABLE_SWITCH,
MYSQLND_QC_TTL_SWITCH,
2);
$sql = sprintf("/*%s*//*%s%d*/SELECT id FROM test WHERE id = 1", MYSQLND_QC_ENABLE_SWITCH, MYSQLND_QC_TTL_SWITCH, 2);
$res = $mysqli->query($sql);
var_dump($res->fetch_assoc());
$res->free();
@ -671,7 +673,7 @@ printf("Script runtime\t: %d seconds\n", microtime(true) - $start);
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
Default TTL : 30 seconds
@ -687,7 +689,6 @@ NULL
Script runtime : 3 seconds
]]>
</screen>
</example>
</para>
</section>
@ -731,22 +732,22 @@ mysqlnd_qc.collect_statistics=1
<?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
);
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;
/* 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;
printf("is_select(%45s): do not cache\n", $query);
return false;
}
/* install callback */
mysqlnd_qc_set_is_select("is_select");
@ -894,8 +895,8 @@ $mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");
/* dummy queries to fill the query trace */
for ($i = 0; $i < 2; $i++) {
$res = $mysqli->query("SELECT 1 AS _one FROM DUAL");
$res->free();
$res = $mysqli->query("SELECT 1 AS _one FROM DUAL");
$res->free();
}
/* dump trace */
@ -903,7 +904,7 @@ var_dump(mysqlnd_qc_get_query_trace_log());
?>
]]>
</programlisting>
&examples.outputs;
&examples.outputs;
<screen>
<![CDATA[
array(2) {
@ -980,31 +981,32 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* dummy queries to fill the query trace */
for ($i = 0; $i < 3; $i++) {
$res = $mysqli->query("SELECT id FROM test WHERE id = " . $mysqli->real_escape_string($i));
$res->free();
$res = $mysqli->query("SELECT id FROM test WHERE id = " . $mysqli->real_escape_string($i));
$res->free();
}
$trace = mysqlnd_qc_get_query_trace_log();
$summary = array();
foreach ($trace as $entry) {
if (!isset($summary[$entry['query']])) {
$summary[$entry['query']] = array(
"executions" => 1,
"time" => $entry['run_time'] + $entry['store_time'],
);
} else {
$summary[$entry['query']]['executions']++;
$summary[$entry['query']]['time'] += $entry['run_time'] + $entry['store_time'];
}
if (!isset($summary[$entry['query']])) {
$summary[$entry['query']] = array(
"executions" => 1,
"time" => $entry['run_time'] + $entry['store_time'],
);
} else {
$summary[$entry['query']]['executions']++;
$summary[$entry['query']]['time'] += $entry['run_time'] + $entry['store_time'];
}
}
foreach ($summary as $query => $details) {
printf("%45s: %5dms (%dx)\n",
$query, $details['time'], $details['executions']);
printf("%45s: %5dms (%dx)\n",
$query, $details['time'], $details['executions']);
}
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
DROP TABLE IF EXISTS test: 0ms (1x)
@ -1068,18 +1070,17 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* dummy queries */
for ($i = 1; $i <= 4; $i++) {
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
MYSQLND_QC_ENABLE_SWITCH,
$i % 2);
$res = $mysqli->query($query);
$res->free();
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2);
$res = $mysqli->query($query);
$res->free();
}
var_dump(mysqlnd_qc_get_core_stats());
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(26) {
@ -1171,17 +1172,17 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* dummy queries to fill the query trace */
for ($i = 1; $i <= 4; $i++) {
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
MYSQLND_QC_ENABLE_SWITCH,
$i % 2);
$res = $mysqli->query($query);
$res->free();
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2);
$res = $mysqli->query($query);
$res->free();
}
var_dump(mysqlnd_qc_get_cache_info());
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(4) {
@ -1335,17 +1336,17 @@ $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* dummy queries to fill the query trace */
for ($i = 1; $i <= 4; $i++) {
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
MYSQLND_QC_ENABLE_SWITCH,
$i % 2);
$res = $mysqli->query($query);
$res->free();
$query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2);
$res = $mysqli->query($query);
$res->free();
}
var_dump(mysqlnd_qc_get_normalized_query_trace_log());
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
array(4) {
@ -1481,118 +1482,118 @@ ini_set("mysqlnd_qc.cache_by_default", 1);
$__cache = array();
function get_hash($host_info, $port, $user, $db, $query) {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
return md5(sprintf("%s%s%s%s%s", $host_info, $port, $user, $db, $query));
return md5(sprintf("%s%s%s%s%s", $host_info, $port, $user, $db, $query));
}
function find_query_in_cache($key) {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
if (isset($__cache[$key])) {
$tmp = $__cache[$key];
if ($tmp["valid_until"] < time()) {
unset($__cache[$key]);
$ret = NULL;
if (isset($__cache[$key])) {
$tmp = $__cache[$key];
if ($tmp["valid_until"] < time()) {
unset($__cache[$key]);
$ret = NULL;
} else {
$ret = $__cache[$key]["data"];
}
} else {
$ret = $__cache[$key]["data"];
$ret = NULL;
}
} else {
$ret = NULL;
}
return $ret;
return $ret;
}
function return_to_cache($key) {
/*
/*
Called on cache hit after cached data has been processed,
may be used for reference counting
*/
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
*/
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
}
function add_query_to_cache_if_not_exists($key, $data, $ttl, $run_time, $store_time, $row_count) {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
$__cache[$key] = array(
"data" => $data,
"row_count" => $row_count,
"valid_until" => time() + $ttl,
"hits" => 0,
"run_time" => $run_time,
"store_time" => $store_time,
"cached_run_times" => array(),
"cached_store_times" => array(),
);
$__cache[$key] = array(
"data" => $data,
"row_count" => $row_count,
"valid_until" => time() + $ttl,
"hits" => 0,
"run_time" => $run_time,
"store_time" => $store_time,
"cached_run_times" => array(),
"cached_store_times" => array(),
);
return TRUE;
return TRUE;
}
function query_is_select($query) {
printf("\t%s('%s'): ", __FUNCTION__, $query);
printf("\t%s('%s'): ", __FUNCTION__, $query);
$ret = FALSE;
if (stristr($query, "SELECT") !== FALSE) {
/* cache for 5 seconds */
$ret = 5;
}
$ret = FALSE;
if (stristr($query, "SELECT") !== FALSE) {
/* cache for 5 seconds */
$ret = 5;
}
printf("%s\n", (FALSE === $ret) ? "FALSE" : $ret);
return $ret;
printf("%s\n", (FALSE === $ret) ? "FALSE" : $ret);
return $ret;
}
function update_query_run_time_stats($key, $run_time, $store_time) {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
if (isset($__cache[$key])) {
$__cache[$key]['hits']++;
$__cache[$key]["cached_run_times"][] = $run_time;
$__cache[$key]["cached_store_times"][] = $store_time;
}
if (isset($__cache[$key])) {
$__cache[$key]['hits']++;
$__cache[$key]["cached_run_times"][] = $run_time;
$__cache[$key]["cached_store_times"][] = $store_time;
}
}
function get_stats($key = NULL) {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
if ($key && isset($__cache[$key])) {
$stats = $__cache[$key];
} else {
$stats = array();
foreach ($__cache as $key => $details) {
$stats[$key] = array(
'hits' => $details['hits'],
'bytes' => strlen($details['data']),
'uncached_run_time' => $details['run_time'],
'cached_run_time' => (count($details['cached_run_times']))
? array_sum($details['cached_run_times']) / count($details['cached_run_times'])
: 0,
);
if ($key && isset($__cache[$key])) {
$stats = $__cache[$key];
} else {
$stats = array();
foreach ($__cache as $key => $details) {
$stats[$key] = array(
'hits' => $details['hits'],
'bytes' => strlen($details['data']),
'uncached_run_time' => $details['run_time'],
'cached_run_time' => (count($details['cached_run_times']))
? array_sum($details['cached_run_times']) / count($details['cached_run_times'])
: 0,
);
}
}
}
return $stats;
return $stats;
}
function clear_cache() {
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
global $__cache;
printf("\t%s(%d)\n", __FUNCTION__, func_num_args());
$__cache = array();
return TRUE;
$__cache = array();
return TRUE;
}
/* Install procedural user-defined storage handler */
if (!mysqlnd_qc_set_user_handlers("get_hash", "find_query_in_cache",
"return_to_cache", "add_query_to_cache_if_not_exists",
"query_is_select", "update_query_run_time_stats",
"get_stats", "clear_cache")) {
printf("Failed to install user-defined storage handler\n");
"return_to_cache", "add_query_to_cache_if_not_exists",
"query_is_select", "update_query_run_time_stats", "get_stats", "clear_cache")) {
printf("Failed to install user-defined storage handler\n");
}
@ -1629,7 +1630,7 @@ $res->free();
?>
]]>
</programlisting>
&examples.outputs.similar;
&examples.outputs.similar;
<screen>
<![CDATA[
query_is_select('DROP TABLE IF EXISTS test'): FALSE
@ -1693,11 +1694,9 @@ NULL
]]>
</screen>
</example>
</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file