Dapper + SQL Server: C# 문자열, 인덱스를 파괴한다!
Dapper를 사용한 C# 코드에서 문자열 매개변수 타입 불일치로 인해 SQL Server 인덱스(Index)가 무시되는 문제 발생
C#의 `string`은 Dapper를 통해 `nvarchar(4000)`로 매핑되지만, SQL Server `varchar` 컬럼(Column)에는 암시적 변환(Implicit Conversion) 발생
성능 저하(Performance Degradation)의 원인은 SQL Server가 인덱스를 사용하지 못하고 전체 테이블을 스캔하기 때문임
해결책은 `DbType.AnsiString`을 사용하여 매개변수 타입을 명시적(Explicitly)으로 지정하고, 코드에 주석을 추가하여 유지보수성을 높이는 것
Dapper와 SQL Server의 타입 매핑 문제
Dapper를 사용하여 C#에서 SQL Server 쿼리를 실행할 때, C#의 `string` 타입이 SQL Server의 `nvarchar(4000)`로 기본 매핑되는 점이 문제의 핵심이다. 특히, SQL Server의 `varchar` 타입 컬럼에 대해 이 매핑이 적용되면, SQL Server는 인덱스를 활용하지 못하고 CONVERT_IMPLICIT 연산을 수행하여 전체 테이블 스캔을 실행한다. 이는 쿼리 성능을 심각하게 저하시키는 원인이 된다. 데이터 격리 아키텍처(Data Isolation Architecture) 관점에서, 데이터 타입의 불일치는 예상치 못한 성능 병목을 유발할 수 있다.
성능 저하의 심각성과 영향
문제 발생 시, 쿼리 실행 시간은 수 밀리초에서 수 천 밀리초로 증가하며, CPU 사용률 또한 급증한다. 이는 쿼리 실행 빈도가 높은 환경에서 더욱 치명적인 영향을 미친다. 예를 들어, 100만 개의 로우(Row)를 가진 테이블에서 인덱스 스캔 대신 전체 스캔이 발생하면, 수십 배 이상의 논리적 읽기(Logical Reads)가 발생한다. 성능 최적화(Performance Optimization) 관점에서, 이러한 타입 불일치는 시스템 전체의 응답 속도 저하를 초래할 수 있다.
문제 해결을 위한 구체적인 방법
문제 해결을 위해, Dapper 쿼리 시 `DbType.AnsiString`을 사용하여 매개변수 타입을 명시적으로 `varchar`로 지정해야 한다. 또한, 컬럼의 크기(size)를 정확히 일치시켜야 한다. 익명 객체(anonymous objects) 대신 `DynamicParameters`를 사용하는 것이 권장되며, 코드에 주석을 추가하여 향후 유지보수 시에도 문제 발생을 방지해야 한다. 코드 가독성(Code Readability)과 유지보수성(Maintainability)을 고려하여, 명확한 의도를 코드에 반영하는 것이 중요하다.
실제 적용 사례 및 성능 개선 효과
문제 해결 후, 쿼리 실행 시간은 현저하게 감소하며, 인덱스 스캔이 정상적으로 수행된다. 예를 들어, 실행 시간은 수 밀리초에서 수 마이크로초로 단축될 수 있으며, 논리적 읽기(Logical Reads) 횟수 또한 크게 감소한다. 이러한 성능 개선은 CPU 사용률 감소로 이어져, 시스템 전체의 효율성을 향상시킨다. 성능 튜닝(Performance Tuning) 관점에서, 데이터 타입의 정확한 지정은 쿼리 성능 최적화의 핵심 요소이다.
문제 진단 및 예방을 위한 방법
문제 발생 여부를 확인하기 위해, 쿼리 저장소(Query Store)를 사용하여 암시적 변환(Implicit Conversion)이 발생하는 쿼리를 식별할 수 있다. 또한, 실행 계획(Execution Plan)에서 `CONVERT_IMPLICIT` 경고를 확인하거나, 코드 내에서 `varchar` 컬럼에 `string` 타입 매개변수를 사용하는 Dapper 쿼리를 검색할 수 있다. 지속적인 모니터링(Continuous Monitoring)을 통해, 잠재적인 성능 문제를 사전에 예방하는 것이 중요하다.