Laravel连接SQLSRV查询速度过慢,如何优化配置?
问题场景
我使用Microsoft SQL Server数据库,分别通过两种方式执行相同查询:
Laravel的DB类和Eloquent:
DB::select(DB::raw("select * from [table]"));Items::select('*')->get();执行时间均为1397毫秒。
直接使用php_pdo_sqlsrv库:
$conn = sqlsrv_connect("192.168.0.100, 51484", $connectionInfo); $tsql = "select * from [table]"; sqlsrv_query($conn, $tsql, array(), array());执行时间仅为52毫秒。
需要调整Laravel中的哪些配置来提升查询速度?
环境信息
- PHP版本:
PHP 8.1.2 (cli) (built: Jan 19 2022 10:18:23) (ZTS Visual C++ 2019 x64) Copyright (c) The PHP Group Zend Engine v4.1.2, Copyright (c) Zend Technologies - PHP扩展库:
php_sqlsrv_81_ts_x64.dll php_pdo_sqlsrv_81_ts_x64.dll - Laravel版本:
Laravel Framework 9.47.0 - 当前数据库配置(
/config/database.php):<?php return [ 'default' => env('DB_CONNECTION', 'sqlsrv'), 'connections' => [ // ...其他连接 'sqlsrv' => [ 'driver' => 'sqlsrv', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST'), 'port' => env('DB_PORT'), 'database' => env('DB_DATABASE'), 'username' => env('DB_USERNAME'), 'password' => env('DB_PASSWORD'), 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, // 'encrypt' => env('DB_ENCRYPT', 'yes'), // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), ], // ...其他连接 ], ];
优化配置建议
1. 启用连接池
Laravel默认未开启SQL Server连接池,而原生sqlsrv可能复用了连接,可在sqlsrv连接配置中添加:
'pool' => [ 'min' => env('DB_POOL_MIN', 2), 'max' => env('DB_POOL_MAX', 10), 'timeout' => env('DB_POOL_TIMEOUT', 30), ],
当前使用的php_pdo_sqlsrv 8.1版本支持连接池,启用后可避免重复建立连接的开销。
2. 调整加密与证书验证设置
注释的加密配置可能导致Laravel默认使用加密连接,而原生sqlsrv未启用加密,这会增加额外耗时。尝试调整为与原生连接一致:
'encrypt' => env('DB_ENCRYPT', 'no'), 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'true'),
若数据库服务器无需加密,关闭加密能大幅减少连接与传输开销。
3. 优化字符集设置
Laravel配置的utf8字符集可能与SQL Server默认字符集不匹配,导致额外的字符转换损耗。尝试调整为数据库实际使用的字符集:
'charset' => 'utf8mb4',
或直接使用SQL Server默认的SQL_Latin1_General_CP1_CI_AS。
4. 关闭查询日志
Laravel默认记录查询日志,在性能测试或生产环境关闭可减少开销。在sqlsrv配置中添加:
'logging' => env('DB_LOGGING', false),
也可在代码中临时关闭:
DB::connection()->disableQueryLog();
5. 添加PDO优化选项
在sqlsrv连接配置中添加与原生sqlsrv对齐的PDO选项:
'options' => [ PDO::ATTR_PERSISTENT => true, // 启用持久连接 PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true, // 直接获取数值类型,避免类型转换 ],
持久连接减少重复连接耗时,数值类型优化减少数据处理开销。
6. 排查Eloquent额外开销
若Eloquent查询慢,可能是模型的全局作用域、预加载、观察者等导致额外逻辑。可先测试无额外逻辑的查询:
Items::select('*')->withoutGlobalScopes()->get();
同时检查模型boot方法是否有不必要的逻辑。
验证优化效果
每次调整配置后,清除配置缓存再测试:
php artisan config:clear
对比优化前后的查询执行时间,确认效果。
内容的提问来源于stack exchange,提问作者Christoforos Pantazis

