PHP SQLSRV 在 sqlsrv_fetch_array/sqlsrv_fetch 上有间歇性延迟

标签 php performance adodb sqlsrv

我们将数据库连接从 ADODB 切换到 SQLSRV,我似乎遇到了问题,导致使用 sqlsrv_fetch_array 出现间歇性延迟。

我在我的数据库中执行查询,返回大约 426 行和 5 个字段。

代码看起来像这样(出于速度基准的目的,我真的删除了它正在做的任何其他事情):

$conn = sqlsrv_connect( $host, array("UID"=>$userName,"PWD"=>$password,"Database"=>$dbName,"QuotedId"=>false, "CharacterSet" =>"UTF-8");

$rsText=sqlsrv_query($conn,$sqlStr,array(),
                array(
                    "Scrollable"=>SQLSRV_CURSOR_STATIC
                ));

$row = array(1);
while(count($row) != 0){
    $row=sqlsrv_fetch_array($rsText,SQLSRV_FETCH_BOTH, SQLSRV_SCROLL_NEXT);
}

使用 ADODB 运行它需要大约 50 毫秒。使用 sqlsrv 运行它需要 500-1000 毫秒。使用 sqlsrv 的原始查询 (sqlsrv_query) 实际上比 ADODB 更快,但是使用 sqlsrv_fetch_array 存在随机时间延迟(我实际上使用 sqlsrv_fetch 进行了测试并且也得到了它们)。我每次调用它时都以毫秒为单位计时,虽然每次调用通常为 0-1 毫秒,但有时会达到 15 毫秒。为什么我说它是随机的是因为如果我多次重新运行代码,延迟不会发生在同一个地方并且数量会有所不同,所以这不是因为特定的行很大(它们都不是) .

有没有人知道我能看到什么可以做到这一点,无论是某个地方的参数还是配置?我不认为它与服务器/网络相关,因为 ADODB 从来没有这样做过。我们使用 PHP 5.6 和 php_sqlsrv_56_ts.dll/php_pdo_sqlsrv_56_ts.dll 和 SQL Server 2008。

谢谢!

最佳答案

按照 alalp 在评论中的建议,我尝试修改滚动类型并解决了问题。

我做了一些快速基准测试,这是我得到的结果:

SQLSRV_CURSOR_STATIC、SQLSRV_CURSOR_KEYSET 和 SQLSRV_CURSOR_DYNAMIC:严重的速度问题。如原帖所述,即使循环遍历中等数量的记录(几百条)也需要一秒钟的时间。

SQLSRV_CURSOR_FORWARD:没有速度问题。循环遍历我示例中的记录需要大约 50 毫秒,这与 ADODB 相同。您失去了执行 MoveFirst/MovePrev 的能力,但我认为这很容易解决,如果需要,可以通过在第一次传递时将结果存储在数组中,或者根据查询,在极少数情况下重新运行它可能会很好需要。

SQLSRV_CURSOR_CLIENT_BUFFERED:速度极快(在我的示例中为 0 毫秒,这是有道理的,因为根据我的理解,这与将整个内容存储在数组中基本相同)。不过,我们在一些较大的数据集中确实存在内存问题。

在我们的项目中,我们最终对公共(public)网站使用了 SQLSRV_CURSOR_CLIENT_BUFFERED,因为在一个页面中从未提取过任何主要数据集,而对后端使用 SQLSRV_CURSOR_FORWARD,您最终可以提取 1000 行数据。

关于PHP SQLSRV 在 sqlsrv_fetch_array/sqlsrv_fetch 上有间歇性延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36869716/

相关文章:

PHP:从 PHP 运行 shell 命令?

c - glVertexAttribPointer、交错元素和性能/缓存友好性

sql - SQL Server 上的慢更新,即使没有记录更新

performance - 在嵌套列表中填充数据的最快方法

mysql - 单个查询中的多个 in select 语句

excel - 导入excel文件对现有数据返回null

php - 从外部 PHP 检查 Drupal 身份验证

php - 如何在 php 中创建一个填充前四个星期的下拉菜单

php - Symfony2 - UniqueEntity 无法使用两个字段的ignoreNull

php ADODB 在连接到 MySQL 之前调用 mysql_options()