【问题标题】:sqlsrv very slow over networksqlsrv 在网络上非常慢
【发布时间】:2014-12-18 18:12:38
【问题描述】:

我在 PHP (5.5.12) 中使用 sqlsrv(php_pdo_sqlsrv_55_ts.dll 和 php_sqlsrv_55_ts.dll)通过 VPN 隧道连接到 MSSQL 2012 服务器。但是大型结果集的传输速度非常慢。

为此查询在同一台 PC 上通过同一 VPN 隧道测试 SSMS:

SELECT * 
FROM [Data].[dbo].[Logins]
WHERE date >= '2014-01-27 00:00:00.000' AND date < '2014-01-29 00:00:00.000'

在 4 秒内返回大约 100,000 行。在查询运行时检查我的防火墙/VPN 上的传输速率显示为 2,500 KB/s(在 100mbit 网络上)。

使用 PHP:

sqlsrv_configure('ClientBufferMaxKBSize', 1024*1024);
$dbconnect = "SERVER\\HERE";
$dbconinfo = array("UID" => "user", "PWD" => "pass", "Database" => "Data")
$conn = sqlsrv_connect( $dbconnect, $dbconinfo);
$sql = "
SELECT * 
FROM [dbo].[Logins]
WHERE date >= '2014-01-27 00:00:00.000' AND date < '2014-01-29 00:00:00.000'
";

$options = array();
$options["Scrollable"] = SQLSRV_CURSOR_CLIENT_BUFFERED;
$options["QueryTimeout"] = 30000;     

$stmt = sqlsrv_query( $conn, $sql, array(), $options);

运行 40 秒,并且在查询运行时防火墙/VPN 显示低于 150 KB/s。任务管理器显示脚本大约 5% 的 CPU。

我使用 SQLSRV_CURSOR_CLIENT_BUFFERED 只是为了测试,因为它在没有任何 PHP 代码的情况下在自己的缓冲区中读取结果。在没有缓冲的情况下获取每组数据只是稍微慢一点(大约 45 秒)。

我也尝试了导致相同结果的 PDO 版本。

ConnectionPooling 0 或 1 也没有任何区别。

将服务器名称更改为 DNS 与 IP 地址也没有区别。

LogSubsystems -1 和 LogSeverity -1 没有显示任何问题或任何有用的信息。

我什至使用 Wireshark 来观察网络流量,但找不到 PHP 和 SSMS 版本之间的任何大差异。但我对网络层了解不多。

任何想法可能是什么问题或我可以尝试加速 PHP/sqlsrv 的任何想法将不胜感激。

【问题讨论】:

  • 添加更多调试。为代码中的每个 db 调用计时。如果每个呼叫都同样慢,那么它可能与网络有关。如果它只是一个调用(例如连接),那么它是特定于该调用的。
  • 我用相同的结果测试了其他查询。看起来我不能让 sqlsrv 超过 150 KB/s,而 SSMS 快 10 倍。知道我可以通过网络检查什么吗?因为 SSMS 使用完全相同的连接。
  • 我对网络了解不多,但是从 SQL 方面,您可以尝试将结果集缩减为仅需要的数据。去掉SELECT *,只列出需要的字段。
  • 这只是一个测试查询来表明这一点。所有具有大型结果集的 PHP/sqlsrv 查询都非常慢,比 Management Studio 中来自同一台 PC 的完全相同的查询慢 10-15 倍。我不知道为什么。 (如果我使用本地测试 SQL 服务器,PHP 实际上比 SSMS 快,但在网络上它非常慢)

标签: php sql-server networking sqlsrv


【解决方案1】:

为了将获取速度提高 3 倍,请在 sqlsrv_connect 连接选项中使用“MultipleActiveResultSets”=>'0'。

例如:

$db = sqlsrv_connect('127.0.0.1', array('Database'=>'dbname','UID'=> 'sa','PWD'=> 'pass',"CharacterSet" =>"UTF-8","ConnectionPooling" => "1"
                    ,"MultipleActiveResultSets"=>'0'

            ));

【讨论】:

  • 非常感谢!这就是诀窍。它比以前快了大约 10 倍(将查询时间从 40 秒提高到 3.9 秒)。
【解决方案2】:

换一个怎么样

$options["Scrollable"] = SQLSRV_CURSOR_CLIENT_BUFFERED;

$options["Scrollable"] = SQLSRV_CURSOR_FORWARD;

【讨论】:

    【解决方案3】:

    对于慢速 sqlsrv 操作,最常见的“修复”之一是更改可滚动值。我试过了,但没有帮助......事实上 SQLSRV_CURSOR_CLIENT_BUFFERED 导致了不稳定的行为。

    例子:

    $stmt = sqlsrv_query( $this->connection,  $sql, array(), array(
                    "Scrollable"=>SQLSRV_CURSOR_CLIENT_BUFFERED
    ));
    

    我相信较新版本的 sqlsrv(我有 4.3.0)已经对此进行了一些优化,并怀疑最新版本不需要这样做。

    第二个最受欢迎的建议是更改连接选项...我尝试了很多解决方案...但它们确实没有帮助。同样,我认为较新的 sqlsrv 驱动程序已经更改了默认值。

    例子:

        sqlsrv_configure('ClientBufferMaxKBSize', 0);           
    $serverName = Config::get('settings.MS_DB_HOST').", 1433"; 
    $connectionInfo = array( 
        "Database"=>Config::get('settings.MS_DB_NAME'), 
        "UID"=>Config::get('settings.MS_DB_UID'), 
        "PWD"=>Config::get('settings.MS_DB_PWD'),
        "MultipleActiveResultSets"=>'0',
        "connectionpooling"=>"0",
        "TraceOn"=>"0"
    );                  
    $this->connection = sqlsrv_connect($serverName, $connectionInfo);   
    

    所有这些……最终对我有所帮助的是意识到 sqlsrv_connect 是我的罪魁祸首,而且速度非常慢。对于某些应用程序,您不会注意到这一点......但在我的情况下,我正在处理在执行后续 sql 操作之前会不断重新连接到数据库的代码。所以说这需要半秒才能运行......如果你有 10 个不同的 sql 语句,每个语句都连接在自己的“sqlsrv_connect()”上......这(对我来说)可能需要 5 秒。解决方案是重用第一次实例化的连接对象。完成此操作后,性能提升非常显着。

    希望 sqlsrv 库将来可以编写 PHP/MySQL 持久连接之类的程序,而这将不再需要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-29
      • 2018-06-19
      • 1970-01-01
      • 2021-08-09
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多