繁体   English   中英

Mysqli查询性能多查询

[英]Mysqli query performance multi-query

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

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

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

预先感谢您的帮助。

目前的性能约为1200ms。 (对于Facebook图形API查询,平均+ 1000ms)。

注意: 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.04610825ms。
  2. 连接:1.20711326599ms。
  3. 禁止检查:0.405788421631ms。
  4. 获取行:418.189229965ms。
  5. 增量观看次数:472.24655151ms。
  6. 得到top20:94.31447983ms。

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


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

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

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


$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/>';

尝试使用index来计数。 例如COUNT(pageid) 它将加快您的查询。

更新资料

您也可以尝试此链接以获取更多说明

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

无法控制多语句查询的后续语句的执行。
你可以因此使用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()不一定表示尚未执行查询。


编辑:测试案例

为了证明我以前的假设,我创建了一个测试用例:

<?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。

更新af_freefeed SET views = views + 1 WHERE page_id =%s和page_id不在(从af_ban WHERE page_id =%s中选择page_id);

您可以尝试以下方法:

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

替换您的前两个查询。

结果中记录的存在应表明请求资源的用户不受限制。 然后,您可以更新视图。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM