注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

一线天色 天宇星辰

天下武功,唯快不破

 
 
 

日志

 
 

JTDS驱动DB索引失效解决方案  

2012-03-27 16:02:35|  分类: 软件开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    今日,发现有一个用户的用户名含有-字符,导致整个系统查询很慢,通过监控程序发现,该用户的查询基本上扫描了整个索引,因此对应这个用户索引几乎是失效的。

刚开始我们以为,可能是我们使用的ibatis框架导致的,可当我们切换到JDBC的原始程序时,发现也有相同问题,具体代码如下:

Connection conn=null;

       try {

           conn = DBConnection.getConnection();

           String sql = " SELECT top 1   *  FROM personal.member a    WHERE  a.member_name = ?";

           PreparedStatement preparedStatement=conn.prepareStatement(sql);

           preparedStatement.setString(1, "-");

           preparedStatement.executeQuery()  ;

       } catch (Exception e) {

           e.printStackTrace();

       }finally{

           conn.close();

       }

这个语句再平常不过了,但是为什么会引发DB索引失效呢?我们通过DB的监控工具,发现了其使用预编译后,传入的参数是nvarchar(4000)的,而我们DB的索引是使用varchar建立的,因此DB接收到nvarchar(4000)的参数还需要再做一次转码,从narcharvarchar转码导致索引基本上无法匹配,致使索引失效!那为什么会变成nvarchar的呢?我们排查了JTDS的源码,发现如下:

包:net.sourceforge.jtds.jdbc

类:TdsData

方法:getNativeType

代码行:1288~1398

JTDS驱动DB索引失效解决方案 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 当参数是

unicode字符集并且参数小于8k/2则使用narchar(4000)

那该如何修改的呢?只要让他进入下一个else if就好了,但是参数长度是固定的,不可能改变,看来能改变的只能是非unicode的参数。

修正方案:追加参数;sendStringParametersAsUnicode=false

示例如下:

JTDS驱动

驱动名称:net.sourceforge.jtds.jdbc.Driver

驱动链接:jdbc:jtds:sqlserver://192.168.245.55:1433/base_passport;sendStringParametersAsUnicode=false

SQLJDBC4(微软的驱动)

驱动名称:com.microsoft.sqlserver.jdbc.SQLServerDriver

驱动链接:jdbc:sqlserver://192.168.245.55:1433;DatabaseName=base_passport;sendStringParametersAsUnicode=false

原理很简单,只要告诉驱动我们传输的字符不是unicode字符即可。但是告诉了驱动不是unicode字符,那如果我传输了unicode字符集会怎么样的呢?

经过测试,传输unicode的字符、日文、韩文等unicode字符时不会引发数据乱码问题。同时测试过,传输的nvarchar的字符但告诉MSSQlvarhcar的字符,不会引发索引失效问题。相关数据可参考如下文章(链接:http://jtds.sourceforge.net/faq.html)

Determines whether string parameters are sent to the SQL Server database in Unicode or in the default character encoding of the database. This seriously affects SQL Server 2000 performance since it does not automatically cast the types (as 7.0 does), meaning that if a index column is Unicode and the string is submitted using the default character encoding (or the other way around) SQLServer will perform an index scan instead of an index seek. For Sybase, determines if strings that cannot be encoded in the server's charset are sent as unicode strings. There is a performance hit for the encoding logic so set this option to false if unitext or univarchar data types are not in use or if charset is utf-8.

文中称2000存在varhcar的数据,narchar的索引会引发索引失效,从2005的版本以后已经修复该问题。

同时测试其他数据库,oraclemysql没有类似情况,因为这两款数据库默认采用的是nvarchar的字符做索引。

 

  评论这张
 
阅读(1699)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017