分类: SQLServer
一个由sendStringParametersAsUnicode参数引起的血案 - SQLServer

业务背景:系统是基于国内某知名底代码平台,数据库是SQLServer2019企业版,在上面开发搭建业务系统。
sendStringParametersAsUnicode是一个 JDBC 驱动连接参数,主要用于 Microsoft SQL Server 的 JDBC 驱动(如 Microsoft JDBC Driver for SQL Server) 中,用于控制 字符串参数(如 VARCHAR、CHAR)在发送到数据库时是否以 Unicode 格式(即 NVARCHAR、NCHAR)传输。

在一次升级JDBC驱动时,丢掉了sendStringParametersAsUnicode=false这个参数,在早高峰期间出现系统页面卡顿,数据库CPU标升,如下图所示:
cpu.png

大量动态查询SQL强制带了nvarchar(4000) 如下所示,占用大量资源·

nvarchar卡住.jpg

-- 类似脚本
exec sp_executesql N'SELECT * FROM XXXX WHERE BOID= @P0 AND BOFIELDNAME= @P1 ORDER BY FILENAME ASC,CREATEDATE DESC',N'@P0 nvarchar(4000),@P1 nvarchar(4000)',N'',N'DBDJBGFJ' 

经过排查,该平台公共模块的几个高频表的几个字段是char类型,结果查询时都用了nvarchar,无法直接命中,按主键查才会出现非常大的逻辑读,就相当于隐式转换,不会走索引。

sendStringParametersAsUnicode默认为true,如不带这个参数默认也就是true

所有 Java 的 String 类型参数(即使对应数据库字段是 VARCHAR)都会被 JDBC 驱动以 Unicode(NCHAR/NVARCHAR) 的方式发送。
这是为了保证字符集兼容性(尤其处理非 ASCII 字符时),但可能导致:
隐式类型转换:SQL Server 需要将 NVARCHAR 转换为 VARCHAR。
索引失效:如果字段上有索引,而查询参数是 NVARCHAR 类型,可能无法命中 VARCHAR 字段上的索引(因为数据类型不匹配)。
性能下降:尤其在高并发或大数据量场景下。

设置为 false 的作用:

当 sendStringParametersAsUnicode=false:
对于数据库字段类型为 VARCHAR/CHAR 的参数,JDBC 驱动会以 非 Unicode(即 VARCHAR/CHAR) 方式发送字符串。
避免不必要的隐式转换,提升查询性能,尤其有利于索引使用。
前提:确保你的数据库字段确实是 VARCHAR 类型,且字符集能正确支持应用中的字符串(如只使用 ASCII 或数据库默认 code page 能覆盖的字符)。

这个系统问题比较多,平台代码里面封装的时候字段类型和数据表中不一致等只是冰山一角。屎山感拉满。
shit.png


相关博文:

发表新评论