php中mysql資料庫非同步查詢實現

來源:互聯網
上載者:User

問題

通常一個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資料庫負載不高的情況下,使用非同步查詢還是不錯的選擇。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.