rav*_*ren 9 php mysql pdo prepared-statement
我正在编写一个半简单的数据库包装类,并希望有一个自动运行的提取方法:它应该只在第一次准备每个不同的语句,并且只是在连续调用时绑定并执行查询.
我想主要的问题是:如何重新准备相同的MySql语句工作,PDO会神奇地识别语句(所以我没有)并停止操作?
如果没有,我打算通过为每个不同的查询生成唯一键来实现这一目的,并将准备好的语句保存在数据库对象的私有数组中 - 在其唯一键下.我打算以下列方式之一获取数组密钥(我都不喜欢).按优先顺序排列:
basename(__FILE__, ".php") . __LINE__这个方法是这样的(只有在循环中调用我们的方法时这个方法才有效 - 大多数情况下需要这个功能)debug_backtrace有没有类似的经历?虽然我正在为之工作的系统确实值得关注优化(它本周非常大并且在不断增长),但也许我一点也不担心,做我正在做的事情没有性能上的好处?
MySQL(与大多数DBMS一样)将缓存预准备语句的执行计划,因此如果用户A为以下内容创建计划:
SELECT * FROM some_table WHERE a_col=:v1 AND b_col=:v2
Run Code Online (Sandbox Code Playgroud)
(其中v1和v2是绑定变量)然后发送要由DBMS插值的值,然后用户B发送相同的查询(但具有不同的插值值),DBMS不必重新生成计划.即它是DBMS找到匹配计划 - 而不是PDO.
但是,这意味着数据库上的每个操作都需要至少2次往返(第一次显示查询,第二次显示绑定变量),而不是使用文字值进行查询的单次往返,这会引入额外的网络成本.解除引用(和维护)查询/计划缓存还涉及一小部分成本.
关键问题是这个成本是否大于首先产生计划的成本.
虽然(根据我的经验)使用Oracle编写的语句肯定会有性能优势,但我不相信MySQL的情况也是如此 - 但是,很多东西将取决于数据库的结构和复杂性.查询(或更具体地说,优化程序可以找到多少个用于解析查询的选项).
尝试自己测量它(提示:您可能希望将慢查询阈值设置为0并编写一些代码以将文字值转换回写入日志的查询的匿名表示).
好吧,由于我一直在抨击为缓存设置查询键的方法,除了简单地使用查询字符串本身之外,我还做了一个简单的基准测试。以下比较了使用纯查询字符串与首先创建 md5 哈希值的情况:
$ php -v
$ PHP 5.3.0-3 with Suhosin-Patch (cli) (built: Aug 26 2009 08:01:52)
$ ...
$ php benchmark.php
$ PHP hashing: 0.19465494155884 [microtime]
$ MD5 hashing: 0.57781004905701 [microtime]
$ 799994
Run Code Online (Sandbox Code Playgroud)
代码:
<?php
error_reporting(E_ALL);
$queries = array("SELECT",
"INSERT",
"UPDATE",
"DELETE",
);
$query_length = 256;
$num_queries = 256;
$iter = 10000;
for ($i = 0; $i < $num_queries; $i++) {
$q = implode('',
array_map("chr",
array_map("rand",
array_fill(0, $query_length, ord("a")),
array_fill(0, $query_length, ord("z")))));
$queries[] = $q;
}
echo count($queries), "\n";
$cache = array();
$side_effect1 = 0;
$t = microtime(true);
for ($i = 0; $i < $iter; $i++) {
foreach ($queries as $q) {
if (!isset($cache[$q])) {
$cache[$q] = $q;
}
else {
$side_effect1++;
}
}
}
echo microtime(true) - $t, "\n";
$cache = array();
$side_effect2 = 0;
$t = microtime(true);
for ($i = 0; $i < $iter; $i++) {
foreach ($queries as $q) {
$md5 = md5($q);
if (!isset($cache[$md5])) {
$cache[$md5] = $q;
}
else {
$side_effect2++;
}
}
}
echo microtime(true) - $t, "\n";
echo $side_effect1 + $side_effect2, "\n";
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2452 次 |
| 最近记录: |