MSSQL을 사용할 때
인덱스가 걸려있는 VARCHAR 컬럼데이터를 조회시 NVARCHAR로 데이터를 넘길경우
인덱스가 걸리지 않아 성능에 문제가 발생하는 사례가 존재한다.
(쿼리분석기에서는 빠른데 미들웨어에서 호출 시 느린경우)
하여 보통은 jtds 드라이버 설정시
sendStringParametersAsUnicode=false
값을 주어 유니코드 처리하지 않게 함으로서 VARCHAR로 처리 되도록 하여 해결을 하고 있다.
근데 문제는
VARCHAR 와 NVARCHAR 가 섞여있을 경우에는 어떻게 해야 하는가?
사실 이문제는 아래와 같이 풀면 해결이 될거라고 생각했다.
1) 드라이버에서는 유니코드를 사용하지 않음 처리.
- sendStringParametersAsUnicode=false
2) mybatis mapper 에 jdbcType 을 부여
- #{column, jdbcType=NVARCHAR}
혹은 1)번을 부여하지 않고( default 는 sendStringParametersAsUnicode=true 이다. )
#{column, jdbcType=NVARCHAR} 와 #{column, jdbcType=VARCHAR} 를 명시해주면 되지 않을까?
라고 생각했었다.
하지만, 결론은 안된다는거...
그래서 jtds 드라이버 소스코드를 살펴 보았다.
역시...NVARCHAR 사용을 위한 setNString() 에서 아래와 같은 코드로 구현이 되어있었고,
[ JtdsCallableStatement.java ]
public void setNString(String parameterName, String value)
throws SQLException {
// TODO Auto-generated method stub
throw new AbstractMethodError();
}
public void setNString(int parameterIndex, String value)
throws SQLException {
// TODO Auto-generated method stub
throw new AbstractMethodError();
}
실제 TdsData.java ( getNativeType 메소드 ) , Support.java ( getJdbcTypeName 메소드 )내에서 지원가능한 jdbcType 검사를 하는데 여기에도 NVARCHAR 가 누락이 되어있다.
그럼 어떻게 NVARCHAR 를 지원하고 있었던걸까?
결론은 이렇다.
jtds 에서는 모든 NVARCHAR 든 VARCHAR 든 VARCHAR 로 인식하고 드라이버에 설정된 유니코드 사용여부에 따라 VARCHAR를 변환하고 있었던 것이다.
'모' 아니면 '도' 로 말이다.
그렇다면 이부분을 어떻게 해결할 수 있을까?
답은 간단하다.
setNString 구간에 setString 을 참조하여 내용을 체워주고,
[ JtdsPreparedStatement.java ]
protected void setParameter(int parameterIndex, Object x, int targetSqlType, int scale, int length)
메소드에 NVARCHAR 타입일 경우 pi.isUnicode = true 로 부여하면,
mybatis에서 NVARCHAR 로 jdbcType 을 부여한 것에 대해서 처리가 가능하다.
이때, mybatis 부분도 수정이 필요한데 이유는 이렇다.
mybatis 의 NVARCHAR 를 처리하는 NStringTypeHandler 라는 클래스가 존재하는데
이 클래스에서 파라미터 바인딩시 setString 이 호출되게 되어있다.
이걸 setNString 을 호출하게 변경하면, 정상처리가 되게 되는 것이다.
이번 기회에 jtds 내에서 어떤 일이 일어나는지 알게된 점이 좋았던거 같다.
그리고 왜 NVARCHAR 를 지원하지 않게 되어있는지...그리고 mybatis에서도 왜 NStringTypeHandler 에서도
setNString 이 아니라 setString 으로 되어있었는지에 대해서는 좀더 고민을 해봐야 할듯하다.
이유가 없지는 않을테니 말이다.
여하튼 이렇게 VARCHAR 와 NVARCHAR 을 Mix 에서 사용하는 곳에서는
이런 부분도 고려가 되어야 할듯하다.
출처 : http://ymseok.blogspot.kr/2013/07/jtds-mssql-nvarchar.html