MySQL异步数据库请求性能


MySQL asynchronous database request performance

我一直在看异步数据库请求在PHP使用mysqlnd。代码工作正常,但是比较性能从一个合理大小的表中提取数据与使用异步请求跨多个表进行相同的数据分割,我没有得到任何像我所期望的性能,尽管它似乎根据硬件设置相当可变。

在我的理解中,我应该达到,而不是:

x = a + b + c + d

:

x = max(a, b, c, d)

其中x为总用时,ad为单个请求用时。我实际看到的是,在一些设置中,性能有相当小的提高,而在其他设置中,性能则更差,就好像请求根本不是异步的一样。欢迎其他可能有过类似经历的人提出任何想法或经验。

编辑:衡量这里的时间,我们讨论的是分布在10个表上的查询,单个查询的完成时间不超过8秒,合并每个单独请求完成的时间(非异步)大约为18秒。

异步执行相同请求的总查询时间也在18秒左右。所以很明显,这些请求并没有对数据库并行执行。

编辑:使用的代码与这里的文档中显示的完全相同

<?php
$link1 = mysqli_connect();
$link1->query("SELECT 'test'", MYSQLI_ASYNC);
$all_links = array($link1);
$processed = 0;
do {
    $links = $errors = $reject = array();
    foreach ($all_links as $link) {
        $links[] = $errors[] = $reject[] = $link;
    }
    if (!mysqli_poll($links, $errors, $reject, 1)) {
        continue;
    }
    foreach ($links as $link) {
        if ($result = $link->reap_async_query()) {
            print_r($result->fetch_row());
            if (is_object($result))
                mysqli_free_result($result);
        } else die(sprintf("MySQLi Error: %s", mysqli_error($link)));
        $processed++;
    }
} while ($processed < count($all_links));
?>

我将扩展我的评论,我将尝试解释为什么使用当前的设置不会获得任何性能。

异步,在您的例子中,意味着检索数据的过程与您的其他代码相比是异步的。两个移动部分(获取数据)和处理数据是分开的,并且一个接一个地执行,但是只有在数据到达时才执行

这意味着您希望充分利用CPU,因此在数据准备好之前不会调用PHP代码。

为了使其工作,您必须控制PHP进程并使其使用操作系统的事件接口之一(Linux上的epoll,或Windows上的IOCP)。由于PHP要么嵌入到web服务器(mod_php),要么作为自己的独立FCGI服务器(php-fpm)运行,这意味着异步数据获取的最佳利用将是当您运行CLI PHP脚本时,因为否则很难利用事件接口。

然而,让我们把重点放在你的问题和为什么你的代码没有更快。

你假设你是CPU限制,你的解决方案是在块中检索数据并以这种方式处理它们-这很好,但是因为你所做的一切都不会产生更快的执行速度,这意味着你是100%的I/O限制。

从数据库中检索数据的过程强制硬盘执行寻道。不管你有多"块",如果磁盘很慢,如果数据分散在磁盘上,那部分就会很慢,创建更多的worker来处理部分数据只会使系统越来越慢,因为每个worker在检索数据时都会遇到同样的问题。

我的结论是,你的问题在于硬盘速度慢,数据集太大,可能不适合构建分块检索。我建议更新这个问题或创建另一个问题,以帮助您更快,更优化地检索数据。