Mysqli查询性能多查询

时间:2013-05-06 06:42:30

标签: php mysql mysqli facebook-php-sdk mysqli-multi-query

我只是希望有人可以通过多次查询来帮助我加快查询速度。

目标: a single multi query to function as the single queries below.

简单的查询,我正在检查一个表以查看用户是否被禁止,如果没有,我正在获取id的行并将其视图计数更新1.如果用户被禁止,我不希望最后查询完成。

提前感谢您的帮助。

目前的表现大约是 1200ms。(对于facebook graph api查询,平均值为+ 1000ms)。

注意: af_freefeed.pageid& af_ban.pageid都在数据库中编入索引。

ALSO:我一直在研究和引用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.04610825ms。
  2. conncect:1.20711326599ms。
  3. 禁止检查:0.405788421631ms。
  4. 获取行:418.189229965ms。
  5. 增量视图:472.24655151ms。
  6. 获得top20:94.31447983ms。

  7. Multi_query#1 如果禁止用户,如何停止多重查询?


    可能的竞争者: 943.8181ms。如果已添加933.1279ms. if banned

    1. 如果禁止退出循环,则为10毫秒差异。这让我相信循环在实际应该执行之前完成所有查询,“next_result”。或者我在如何循环功能方面有错误。

    2. exit;替换为$thread_id = $fconn->thread_id; $fconn->kill($thread_id); 如果被禁止953.4719ms。 没有收获


    3. $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.2499ms。但是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 个答案:

答案 0 :(得分:3)

尝试使用index来计算。例如COUNT(pageid)。它会加快你的查询速度。

<强>更新

您也可以尝试 link 进一步说明

答案 1 :(得分:3)

编辑:现在,结论:(下面的测试用例)

无法控制多语句查询的后续语句的执行 因此,您可以以您希望的方式使用multi_query()

全部执行,或者不执行任何操作。


关于
Multi_query#2 “当前基准”如何在next_result()之后删除结果集中的重复字段?

使用fetch_assoc()fetch_array(MYSQLI_ASSOC)(两者几乎相同)代替fetch_array()


关于multi_query():

我最近使用MySQL C API开发了一个程序,mysqli也使用了它 About multiple-statement query support the documentation states

  

执行多语句字符串可以生成多个结果集或行计数指示符。处理这些结果涉及与单语句情况不同的方法:在处理第一个语句的结果后,有必要检查是否存在更多结果并依次处理它们。为了支持多结果处理,C API包括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()后执行,那么在循环迭代之间添加的sleep(5)调用会导致5秒的延迟。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

  
    

我正在检查一个表以查看用户是否被禁止,如果没有,我将获取id的行并将其视图计数更新为1.

  

以下查询可帮助您更新查看次数。我假设您已经知道page_id。

UPDATE af_freefeed SET views = views + 1 WHERE page_id =%s且page_id not in(从af_ban选择page_id WHERE page_id =%s);

答案 4 :(得分:0)

你可以尝试这些方法:

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

替换前两个查询。

结果中存在记录应指示请求资源的未经审核的用户。然后,您可以更新您的观点。

希望这有帮助。