在使用 MyBatis 操作 SQL Server 資料庫時,執行簡單的更新語句卻發現效能極差。經監控發現,JDBC 驅動程式產生的參數型別為 nvarchar(4000),導致查詢計畫無法有效使用索引,造成全表掃描。
<update id="updateDriverInfoByUcode" parameterType="com.sypro.earth.model.DriverInfo">
update D_DriverInfo
<set>
<if test="driverName != null">
DriverName = #{driverName,jdbcType=NVARCHAR},
</if>
</set>
<where>
Ucode=#{ucode,javaType=string,jdbcType=VARCHAR,typeHandler=com.sypro.earth.typehandler.ExampleTypeHandler}
</where>
</update>
(@P0 nvarchar(4000),@P1 nvarchar(4000)) update D_DriverInfo SET DriverName = @P0 WHERE Ucode=@P1
SQL Server JDBC 驅動程式預設將字串參數視為 Unicode (nvarchar),而資料表欄位若為非 Unicode 型別 (varchar),會導致隱含型別轉換,使索引失效,查詢效能大幅下降。
在連線字串中加入 sendStringParametersAsUnicode=false 參數,強制驅動程式以非 Unicode 型別傳送字串參數。
jdbc:sqlserver://127.0.0.1;databaseName=new;
jdbc:sqlserver://127.0.0.1;databaseName=new;sendStringParametersAsUnicode=false
調整後,監控到的參數型別變為 varchar(8000),查詢計畫正常使用索引,批量更新效能顯著提升。
面對 ORM 框架效能問題時,別忘了檢查底層 JDBC 驅動程式的行為。一個小小的連線字串參數,有時能帶來數量級的效能提升。