Mysqli производительность запросов multi-query
Я просто надеялся, что кто-нибудь может помочь мне ускорить 4 запроса с несколькими запросами.
ЦЕЛЬ: a single multi query to function as the single queries below.
Простые запросы, я проверяю одну таблицу, чтобы увидеть, забанен ли пользователь, затем, если нет, я получаю строку для идентификатора и обновляю количество просмотров на 1. Если пользователь забанен, я не хочу, чтобы последний запрос выполнялся.
Спасибо заранее за вашу помощь.
текущая производительность составляет около1200 мс.(+ 1000 мс средним для запроса API-графика графа Facebook).
ПРИМЕЧАНИЕ: af_freefeed.pageid и af_ban.pageid оба проиндексированы в базе данных.
ТАКЖЕ: я изучал и ссылался наhttp://www.php.net/manual/en/mysqli.multi-query.php
я просто не могу понять, как получить этот конфиг в мульти сif()
$fconn = new mysqli($fdbhost, $fdbuser, $fdbpass, $fdbname) or die ('Error connecting to mysqli');
// 12,000 rows for af_ban - bigint(255) : indexed
$q = sprintf('SELECT COUNT(pageid) AS numrowst FROM af_ban WHERE pageid = %s', $banpage);
$readtop = $fconn->query($q);
$rowtop = $readtop->fetch_assoc();
// 1.17 million rows for af_freefeed - bigint(255) : indexed
if($rowtop[numrowst] == 0){
$q = sprintf('SELECT COUNT(pageid) AS numrowsf FROM af_freefeed WHERE pageid = %s', $banpage);
$readf = $fconn->query($q);
$rowf = $readf->fetch_assoc();
// increment views
$read = $fconn->query("Update af_freefeed SET views = views + 1 WHERE pageid = ".$banpage."");
}
$q=$fconn->query("SELECT pagename,views,pageid FROM af_freefeed ORDER BY views DESC LIMIT 0, 20");
unset($q);
unset($rowf);
unset($rowtop);
mysqli_close($fconn);
фактическое время запроса.
- grah api: 1127.04610825мс.
- Concect: 1.20711326599мс.
- проверка запрещена: 0,405788421631мс.
- получить строку: 418.189229965мс.
- количество просмотров: 472.24655151мс.
- получите top20: 94,31447983мс.
Multi_query # 1Как остановить мультизапрос, если пользователь забанен?
Возможный претендент:943,8181мс. если добавлено: 933.1279ms. if banned
Разница в 10 мс, если выходной цикл заблокирован. Это наводит меня на мысль, что цикл завершает все запросы до того, как они фактически должны быть выполнены, "next_result". Или у меня ошибка в том, как я зациклил функции.
заменены
exit;
с$thread_id = $fconn->thread_id; $fconn->kill($thread_id);
если забанен 953.4719мс. нет выгоды.
$banpage='234232874008';
$query = "SELECT pagename,views,pageid FROM af_freefeed ORDER BY views DESC LIMIT 0, 2;";
$query .= "SELECT pageid AS isbanned FROM af_ban WHERE pageid = \"".$banpage."\";";
$query .= "SELECT pageid AS isadded FROM af_freefeed WHERE pageid = \"".$banpage."\";";
$query .= "Update af_freefeed SET views = views + 1 WHERE pageid = \"".$banpage."\"";
/* execute multi query */
if ($fconn->multi_query($query)) {
if ($result = $fconn->store_result()) {
while ($row = $result->fetch_row()) {
print_r($row).'<br />';
}
$result->free();
}
if ($fconn->more_results()) {
while ($fconn->next_result()){
if($thisresult = $fconn->store_result()){
while (is_array($row = $thisresult->fetch_array())) {
if(isset($row['isbanned'])){
if($row['isbanned']===''.$banpage.''){
$thread_id = $fconn->thread_id;
$fconn->kill($thread_id);
// exit;
}
}
}
}
}
}
}
unset($query);
unset($result);
unset($thisresult);
Multi_query # 2 "текущий для теста" Как удалить повторяющиеся поля в наборе результатов после next_result ()?
2.667ms. / 1032,2499мс. но print_r показывает повторяющиеся поля в $thisresults?
**Array
(
[0] => 37
[id] => 37
[1] => 159616034235
[pageid] => 159616034235
[2] =>
[userid] =>
[3] => 30343
[views] => 30343
[4] => Walmart
[pagename] => Walmart
)**
$query = "SELECT pageid AS isbanned FROM af_ban WHERE pageid = \"".$banpage."\";";
$query .= "SELECT pageid AS isadded FROM af_freefeed WHERE pageid = \"".$banpage."\";";
$query .= "SELECT * FROM af_freefeed ORDER BY views DESC LIMIT 0, 20";
//$query .= "Update af_freefeed SET views = views + 1 WHERE pageid = \"".$banpage."\"";
/* execute multi query */
echo '<pre>';
$i=0;
if ($fconn->multi_query($query)) {
if ($result = $fconn->store_result()) {
//$row = $result->fetch_assoc();
while ($row = $result->fetch_assoc()) {
print_r($row).'<br />';
}
$result->free();
}
if ($fconn->more_results()) {
while ($fconn->next_result()){
if($thisresult = $fconn->store_result()){
while ($row2 = $thisresult->fetch_array()) {
if(isset($row2['isadded'])){
if($row2['isadded']===''.$banpage.''){
$addone = $fconn->query("Update af_freefeed SET views = views + 1 WHERE pageid = ".$banpage."");
}
}
print_r($row2);
}
}
}
}
}
/* determine our thread id */
$thread_id = $fconn->thread_id;
/* Kill connection */
$fconn->kill($thread_id);
//
echo '</pre><hr/>';
5 ответов
РЕДАКТИРОВАТЬ: Итак, теперь вывод: (тестовый пример ниже)
Вы не можете контролировать выполнение последующих операторов запроса из нескольких операторов.
Поэтому вы не можете использовать multi_query()
так, как вы хотели.
Выполните их все или не выполняйте ни одного.
относительно
Multi_query # 2 "текущий для теста" Как удалить повторяющиеся поля в наборе результатов после next_result()?
использование fetch_assoc()
или же fetch_array(MYSQLI_ASSOC)
(оба практически одинаковые) вместо fetch_array()
,
О multi_query():
Недавно я работал над программой, использующей MySQL C API, которую также использует mysqli.
О поддержке запросов из нескольких операторов в документации говорится:
Выполнение строки с несколькими операторами может привести к множеству результирующих наборов или индикаторов числа строк. Обработка этих результатов включает иной подход, чем для случая с одним оператором: после обработки результата из первого оператора необходимо проверить, существуют ли еще результаты, и обработать их по очереди, если это так. Для поддержки обработки нескольких результатов API C включает функции mysql_more_results() и mysql_next_result(). Эти функции используются в конце цикла, который повторяется до тех пор, пока доступно больше результатов. Невозможность обработать результат таким способом может привести к обрыву соединения с сервером.
(подчеркните добавлено)
Это приводит к выводу, что прерывание запроса с несколькими операторами не является предполагаемой функцией.
Более того, я не нашел никакого ресурса, объясняющего, когда последующие запросы фактически выполняются.
призвание next_result()
не обязательно означает, что запрос еще не выполнен.
РЕДАКТИРОВАТЬ: ТЕСТ ДЕЛО
Чтобы доказать, что я ранее предполагал, я создал контрольный пример:
<?php
$db = new mysqli('localhost', 'root', '', 'common');
$query = 'SELECT NOW() as time;';
$query .= 'SELECT NOW() as time;';
$query .= 'SELECT NOW() as time;';
$query .= 'SELECT NOW() as time;';
if($db->multi_query($query)) {
// Current time
echo "'multi_query()' executed at:\n\t\t"
.date('Y-m-d H:i:s')."\n";
// First result
if($result = $db->store_result()) {
$i = 1;
$row = $result->fetch_assoc();
echo "'NOW()' of result $i:\n\t\t".$row['time']."\n";
$result->free();
// Wait 5 seconds
sleep(5);
// Subsequent results
while($db->more_results() && $db->next_result()) {
$result = $db->store_result();
$row = $result->fetch_assoc();
$i++;
echo "'NOW()' of result $i:\n\t\t".$row['time']."\n";
// Wait 5 seconds
sleep(5);
$result->free();
}
}
}
$db->close();
?>
Это приводит к:
'multi_query()' executed at:
2013-05-10 10:18:47
'NOW()' of result 1:
2013-05-10 10:18:47
'NOW()' of result 2:
2013-05-10 10:18:47
'NOW()' of result 3:
2013-05-10 10:18:47
'NOW()' of result 4:
2013-05-10 10:18:47
Учитывая это, очевидно, что все четыре оператора запроса были выполнены непосредственно после вызова multi_query()
,
Если они были выполнены только после вызова next_result()
будет 5 секундная задержка, вызванная sleep(5)
звонки, которые я добавил между итерациями цикла.
Попробуй использовать index
в подсчете. Как например COUNT(pageid)
, Это ускорит ваш запрос.
Обновить
Вы также можете попробовать эту ссылку для дальнейшего объяснения
Я проверяю одну таблицу, чтобы увидеть, забанен ли пользователь, а затем, если нет, я получаю строку для идентификатора и обновляю его количество просмотров на 1.
Следующий запрос может помочь вам обновить количество просмотров. Я предполагаю, что вы уже знаете page_id.
ОБНОВЛЕНИЕ af_freefeed SET views=views+1 WHERE page_id=%s и page_id нет (выберите page_id из af_ban WHERE page_id=%s);
Пожалуйста, запустите следующий запрос в MySQL и проверьте время выполнения вашего запроса:
CREATE INDEX pagidIndex ON af_ban (pageid(11));
CREATE INDEX pagidFeedIndex ON af_freefeed (pageid(11));
CREATE INDEX viewsIndex ON af_freefeed (views(11));
Вы можете попробовать что-то вроде этого:
$sql = sprintf("SELECT af_freefeed.pageid FROM af_freefeed left join af_ban ".
"on (af_freefeed.pageid = af_ban.pageid) ".
"where af_freefeed.pageid = %s and ".
"af_ban.pageid is null limit 1", $pageid);
заменить ваши первые два запроса.
Наличие записи в результатах должно указывать на незапрещенного пользователя, запрашивающего ресурс. Затем вы можете обновить ваши взгляды.
Надеюсь это поможет.