NestJS调用SQL Server原生SQL性能低下,是否为配置问题?
解决NestJS + mssql连接SQL Server的性能延迟问题
核心问题分析
你的代码存在两个关键问题导致查询延迟:
- 数据库连接池初始化未等待完成,且池配置不合理,导致查询时可能频繁创建新连接
- 采用字符串拼接生成SQL,不仅存在SQL注入风险,还额外增加了SQL解析开销,无法有效复用连接池资源
具体修复步骤
1. 等待连接池初始化完成后启动应用
原main.ts中sql.connect(sqlConfig)是异步操作,但未加await,导致应用启动时连接池尚未建立,第一次查询会触发连接建立流程,直接增加延迟。修改如下:
async function bootstrap() { // ... 其他代码保持不变 // 等待连接池初始化完成 await sql.connect(sqlConfig); logger.log('App connected to SQL Server database'); // ... 其他代码保持不变 }
2. 调整连接池配置,避免频繁销毁连接
原配置min: 0会导致空闲时关闭所有连接,每次新请求都需要重新建立连接,在Azure环境下网络开销极大。修改pool配置:
pool: { max: 10, min: 3, // 保持3个空闲连接,避免频繁创建 idleTimeoutMillis: 60000, // 延长空闲超时到1分钟 },
3. 改用参数化调用存储过程,放弃字符串拼接
原代码的SQL拼接方式无法利用连接池的预编译和复用能力,同时存在严重的注入风险。修改CrudService的查询逻辑,使用mssql的Request对象调用存储过程:
async find( sp: string, DB: string, body?: FindBodyDTO | null, query?: Record<string, any> | null, email?: string, filter?: string, ): Promise<Record<string, any>[]> { const method = 'find'; const storedProcedure = process.env.SPECIFYDB == 'true' ? `[${DB}].[ml_sp].[${sp}]` : `[ml_sp].[${sp}]`; try { const request = new sql.Request(); // 绑定参数,避免字符串拼接 request.input('method', sql.NVarChar, method); request.input('body', sql.NVarChar, body ? JSON.stringify(body) : null); request.input('query', sql.NVarChar, query ? JSON.stringify(query) : null); request.input('email', sql.NVarChar, email); request.input('filter', sql.NVarChar, filter); // 执行存储过程 const result = await request.execute(storedProcedure); return result.recordset as Record<string, any>[]; } catch (error) { this.logger.error(error); throw new HttpException( fxSQLerrorMsg(error.message, 'Find'), HttpStatus.BAD_REQUEST, ); } }
注意:需同步修改存储过程的参数接收逻辑,确保与传入参数名匹配。
4. 验证连接池复用情况
添加日志监听连接池的连接创建与释放事件,确认连接是否被复用:
// 在main.ts连接完成后添加 sql.on('connect', (connection) => { logger.log(`新连接创建,ID: ${connection.id}`); }); sql.on('release', (connection) => { logger.log(`连接释放,ID: ${connection.id}`); });
若多次查询复用同一个连接ID,说明连接池已生效。
额外优化建议
- Azure SQL Server:将应用部署在与数据库同区域的服务器上,降低网络延迟
- 确认Azure SQL的
Connection Pooling选项处于开启状态(默认开启) - 避免重复序列化JSON对象,可提前处理参数后再传入查询
内容的提问来源于stack exchange,提问作者John G.
相关产品推荐
相关产品推荐

