这可能有点旧了,但我自己在想这个。所以我做了一个基准。首先,我创建了一个简单的表格:
SELECT * from random LIMIT 10;
+----+------------+
| id | rand_stuff |
+----+------------+
| 1 | 1988585319 |
| 2 | 1926594853 |
| 3 | 820681972 |
| 4 | 950331574 |
| 5 | 540721998 |
| 6 | 1284256353 |
| 7 | 12804417 |
| 8 | 2130482967 |
| 9 | 2018786156 |
| 10 | 285818156 |
+----+------------+
SELECT count(id) from random;
+-----------+
| count(id) |
+-----------+
| 3365586 |
+-----------+
/var/lib/mysql/benchmark# ls -laFh
total 101M
drwx------ 2 mysql mysql 4.0K 2011-05-28 00:06 ./
drwxr-xr-x 7 mysql mysql 4.0K 2011-05-27 23:53 ../
-rw-rw---- 1 mysql mysql 65 2011-05-27 23:53 db.opt
-rw-rw---- 1 mysql mysql 8.4K 2011-05-28 00:06 random.frm
-rw-rw---- 1 mysql mysql 55M 2011-05-28 00:32 random.MYD
-rw-rw---- 1 mysql mysql 47M 2011-05-28 00:32 random.MYI
它是一个平凡的结构,重量约为100 MB。随机数是用php的mt_rand()函数创建的。
这里的 “Fetch.php”:
<?php
$loops = $argv[1];
$mysqli = new mysqli("localhost", "bench", "bench", "benchmark");
if(mysqli_connect_errno()){
printf("Connect Failed: %s\n", mysqli_connect_error());
exit();
}
if($stmt = $mysqli->prepare("SELECT rand_stuff FROM random WHERE id = ?")){
for($i=1; $i<$loops; $i++){
$stmt->bind_param("i", $i) or die;
$stmt->execute() or die;
$stmt->bind_result($value) or die;
$stmt->fetch();
echo "$i \t $value\n";
}
$stmt->close();
}
而且一些基准:
$time php fetch.php 10 > /dev/null
real 0m0.043s
user 0m0.024s
sys 0m0.012s
$ time php fetch.php 100 > /dev/null
real 0m0.057s
user 0m0.044s
sys 0m0.000s
$ time php fetch.php 1000 > /dev/null
real 0m0.166s
user 0m0.080s
sys 0m0.012s
$ time php fetch.php 10000 > /dev/null
real 0m1.083s
user 0m0.412s
sys 0m0.124s
这里的fetch2.php
<?php
$loops = $argv[1];
$mysqli = new mysqli("localhost", "bench", "bench", "benchmark");
if(mysqli_connect_errno()){
printf("Connect Failed: %s\n", mysqli_connect_error());
exit();
}
$array = array();
for($i=1; $i<$loops; $i++){
$array[] = $i;
}
$joined_array = join($array, ',');
$results = $mysqli->query("SELECT id, rand_stuff FROM random WHERE id IN ($joined_array)");
while($row = $results->fetch_row()){
$val1 = $row[0];
$val2 = $row[1];
echo "$val1\t$val2\n";
}
这里是其相关的基准。
$time php fetch2.php 10 > /dev/null
real 0m0.037s
user 0m0.028s
sys 0m0.008s
$time php fetch2.php 100 > /dev/null
real 0m0.044s
user 0m0.032s
sys 0m0.008s
$ time php fetch2.php 1000 > /dev/null
real 0m0.050s
user 0m0.036s
sys 0m0.016s
$ time php fetch2.php 10000 > /dev/null
real 0m0.117s
user 0m0.088s
sys 0m0.024s
Side By Side,我们得到这张表(Fetch.php是“WHERE id =?“而准备的语句,而Fetch2.php使用”,其中X IN()”在哑查询语法):
+--------+-----------+------------+
| Loop | Fetch.php | Fetch2.php |
+--------+-----------+------------+
| 10 | .043s | .037s |
| 100 | .057s | .044s |
| 1000 | .116s | .050s |
| 10000 | 1.083s | .117s |
+--------+-----------+------------+
显然, “Fetch2.php” 是更有效的,但在这个基准测试...在进入100多个元素范围之前,它似乎并不重要,对准备好的语句进行迭代是简单和安全的(根本没有SQL注入的机会),而且在〜10时似乎不会太慢重复测试〜10个元素有时可以使得“Fetch.php”赢得基准,总的来说,Fetch2.php当然赢了,但他们肯定是在这个范围内接近。说...如果你有不到100个元素,就利用这个准备d语句并重复执行。这是准备好的声明毕竟是为了设计的。当然,没有什么比单次往返数据库更好,但准备好的陈述方法可能具有可接受的性能。当然,在你自己的系统上进行基准测试。最有可能的是,上面的测试太琐碎了(没有任何连接或子查询......并且db与php脚本在同一个系统上......)
这意味着我想我将不得不使用call_user_func_array来实际调用bind_param方法 – 2010-09-20 16:20:28
您可以循环访问数组。 – webbiedave 2010-09-20 16:23:17
你能详细说明一下吗?怎么样?我只是一次绑定参数。 – 2010-09-20 17:13:58