mysql查询性能多查询


Mysqli query performance multi-query

我只是希望有人能帮助我加快4查询与多查询

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

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

提前感谢您的帮助

当前性能在1200ms左右。 (facebook graph api查询+1000ms avg)。

注意: af_freefeed。pageid,af_ban。

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. 图形api: 1127.04610825ms.
  2. 什么的:1.20711326599 ms。
  3. 检查禁止:0.405788421631ms.
  4. get row: 418.189229965ms.
  5. 增量视图:472.24655151ms.
  6. get top20: 94.31447983ms.

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


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

  1. 10ms的差异,如果退出循环被禁止。这让我相信循环是完成所有的查询之前,他们实际上应该被执行,"next_result"。或者我有一个错误,我如何循环函数。

  2. $thread_id = $fconn->thread_id; $fconn->kill($thread_id);代替exit;如果被禁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.667 ms。/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/>';

尝试使用index获取计数。例如COUNT(pageid)。这会加快你的查询速度。

您也可以尝试这个链接以获得进一步的解释

EDIT:那么现在,结论:(下面的测试用例)

不能控制多语句查询的后续语句的执行。
因此,而不是可以按照您想要的方式使用multi_query()

全部执行,或者不执行。


关于

Multi_query #2"当前为基准"如何在next_result()后的结果集中删除重复字段?

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


关于multi_query ():

我最近做了一个使用MySQL C API的程序,mysqli也使用了。
关于支持多语句查询的文档说明:

执行一个多语句字符串可以产生多个结果集或行计数指示器。处理这些结果涉及到与单语句情况不同的方法:在处理第一个语句的结果之后,有必要检查是否存在更多结果,如果存在,则依次处理。为了支持多结果处理,C API包括mysql_more_results()和mysql_next_result()函数。这些函数在循环结束时使用,只要有更多的结果可用,循环就会迭代。不按此方式处理结果可能会导致与服务器的连接断开。

(强调)

由此得出结论,终止多语句查询并不是一个预期的特性

此外,我没有找到任何资源来解释何时实际执行后续查询。
调用next_result()并不一定意味着查询尚未执行。

EDIT: TEST CASE

为了证明我之前的假设,我创建了一个测试用例:
<?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秒延迟。

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

我正在检查一个表,看看用户是否被禁止,然后如果不是,我得到行id和更新它的视图计数1。

下面的查询可以帮助您更新视图计数。我假设您已经知道page_id。

WHERE page_id=%s and page_id not in (select page_id from af_ban WHERE page_id=%s);

您可以尝试这样做:

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

来替换前两个查询。

结果中存在的记录应该表明未被禁止的用户请求该资源。然后你可以更新你的视图