Возможно, это немного устарело, но мне самому это было интересно. Итак, я выполнил тест. Сначала я создал простую таблицу:
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 МБ. Случайное число было создано с помощью функции 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
Параллельно мы получаем эту таблицу (Fetch.php - это «WHERE id =?» И подготовленные операторы, в то время как Fetch2.php использует синтаксис «WHERE 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 элементов, просто воспользуйтесь подготовленным оператором и выполняйте его повторно. Это то, для чего подготовленные заявления предназначены в конце концов. Конечно, ничто не сравнится с односторонним обращением к базе данных, но подготовленный подход к заявлению может иметь приемлемую производительность. Конечно, тест на вашей собственной системе. Скорее всего, приведенный выше тест был слишком тривиальным (нет никаких объединений или подзапросов ... и БД находится в той же системе, что и скрипт php ...)