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);

фактическое время запроса.

  1. grah api: 1127.04610825мс.
  2. Concect: 1.20711326599мс.
  3. проверка запрещена: 0,405788421631мс.
  4. получить строку: 418.189229965мс.
  5. количество просмотров: 472.24655151мс.
  6. получите top20: 94,31447983мс.

Multi_query # 1Как остановить мультизапрос, если пользователь забанен?


Возможный претендент:943,8181мс. если добавлено: 933.1279ms. if banned

  1. Разница в 10 мс, если выходной цикл заблокирован. Это наводит меня на мысль, что цикл завершает все запросы до того, как они фактически должны быть выполнены, "next_result". Или у меня ошибка в том, как я зациклил функции.

  2. заменены 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);

заменить ваши первые два запроса.

Наличие записи в результатах должно указывать на незапрещенного пользователя, запрашивающего ресурс. Затем вы можете обновить ваши взгляды.

Надеюсь это поможет.

Другие вопросы по тегам