php中mysql數據庫異步查詢實現

一般一個web應用的性能瓶頸在數據庫。由於,一般狀況下php中mysql查詢是串行的。也就是說,若是指定兩條sql語句時,第二條sql語句會等到第一條sql語句執行完畢再去執行。這個時候,若是執行2條sql語句,每條執行時間爲50ms,所有執行完畢可能須要100ms。既然,主要緣由是sql的串行執行致使。那咱們是否是能夠改變執行方式來提升性能呢?答案是,能夠的。咱們能夠經過異步執行的方式來提升性能。
異步

若是經過異步的方式去執行,可能性能會有很大提高。若是是採用異步的方式,兩條sql語句會併發執行,可能就須要60ms就能夠執行完畢。
實現

mysqli + mysqlnd。php官方實現的mysqlnd中提供了異步查詢的方法。分別是:
mysqlnd_async_query 發送查詢請求
mysqlnd_reap_async_query 獲取查詢結果
這樣就能夠沒必要每次發送完查詢請求後,一直阻塞等待查詢結果了。

實現代碼以下:

<!--?php
   
$host       = '127.0.0.1';
$user       = 'root';
$password   = '';
$database   = 'test';
   
/**
 * 指望獲得額結果
 * array(
 *  1 =--> int,
 *  2 => int,
 *  3 => int
 * )
 */
$result = array(1=>0, 2=>0, 3=>0);
   
//異步方式[併發請求]
$time_start = microtime(true);
$links = array();
   
foreach ($result as $key=>$value) {
    $obj = new mysqli($host, $user, $password, $database);
    $links[spl_object_hash($obj)] = array('value'=>$key, 'link'=>$obj);
}
$done = 0;
$total = count($links);
   
foreach ($links as $value) {
    $value['link']->query("SELECT COUNT(*) AS `total` FROM `demo` WHERE `value`={$value['value']}", MYSQLI_ASYNC);
}
   
do {
   
    $tmp = array();
    foreach ($links as $value) {
        $tmp[] = $value['link'];
    }
   
    $read = $errors = $reject = $tmp;
    $re = mysqli_poll($read, $errors, $reject, 1);
    if (false === $re) {
        die('mysqli_poll failed');
    } elseif ($re < 1) {
        continue;
    }
   
    foreach ($read as $link) {
        $sql_result = $link->reap_async_query();
        if (is_object($sql_result)) {
            $sql_result_array = $sql_result->fetch_array(MYSQLI_ASSOC);//只有一行
            $sql_result->free();
            $hash = spl_object_hash($link);
            $key_in_result = $links[$hash]['value'];
            $result[$key_in_result] = $sql_result_array['total'];
        } else {
            echo $link->error, "\n";
        }
        $done++;
    }
   
    foreach ($errors as $link) {
        echo $link->error, "1\n";
        $done++;
    }
   
    foreach ($reject as $link) {
        printf("server is busy, client was rejected.\n", $link->connect_error, $link->error);
        //這個地方別再$done++了。
    }
} while ($done<$total);
var_dump($result);
echo "ASYNC_QUERY_TIME:", microtime(true)-$time_start, "\n";
   
$link = end($links);
$link = $link['link'];
echo "\n";
 結語

mysql數據庫對於每一個查詢請求都是單獨啓動一個線程進行處理。若是mysql服務器啓動線程過多,必然會形成線程切換引發系統負載太高。若是在mysql數據庫負載不高的狀況下,使用異步查詢仍是不錯的選擇。php

相關文章
相關標籤/搜索