oracle, mysql 모두 동일하니 여기에서는 mysql 을 기준으로 작성한다.
아래와 같은 테이블 있다고 가정해보자.
CREATE TABLE TEST (
SEQ bigint(11) NOT NULL AUTO_INCREMENT,
ID_INT int(10),
ID_VARCHAR varchar(10),
PRIMARY KEY (SEQ),
KEY IDX_ID_INT (ID_INT),
KEY IDX_ID_VARCHAR (ID_VARCHAR)
)
일반적으로 알고 있던 지식은 칼럼을 조건으로 조회할 때 해당 칼럼에 타입과 일치하는 값으로 조회을 해야 하고 그렇지 않으면 타입이 달라 인덱스 스캔이 되지 않는다는 것이었다. 맞는 말이긴 하지만 꼭 우리가 명시적으로 그렇게 해줄 필요는 없다.
만약 ID_INT 를 조건으로 조회한다면 아래와 같은 쿼리를 작성할 수 있다.
select * from TEST where ID_INT = '10'
select * from TEST where ID_INT = 10
내가 알고 있던 지식으로는 무조건 두번째 쿼리만 사용해야 하지만 실행계획을 보면 첫번째 쿼리를 사용해도 인덱스가 잘탄다. 이는 쿼리 수행시 조회값에 대해 묵시적 형변환이 발생되기 때문이다. 나는 String 형 값으로 조회했지만 묵시적으로 int 형 값으로 변환된다는 말이다.
그렇다면 ID_VARCHAR 를 조건으로 조회한다면 어떨까?
select * from TEST where ID_VARCHAR = '10'
select * from TEST where ID_VARCHAR = 10
위에서 말한 묵시적 형변환을 생각하면 이것도 아무런 문제가 없을 것 같지만 두번째 쿼리는 인덱스를 타지 않는다. 즉, 묵시적 형변환이 수행되지 않는 것인데 이는 묵시적 형변환의 조건 때문이다.
묵시적 형변환은 칼럼과 조회값의 데이터 타입이 다를 때 조회값의 타입이 칼럼의 타입보다 우선순위가 낮을 경우 칼럼의 타입으로 자동으로 형변환해준다. 모든 타입의 우선순위는 잘 모르겠는데 정수와 문자열만 두고 보면 정수 > 문자열로 문자열이 우선순위가 더 낮다.
이에 ID_INT 의 경우 조회값으로 문자열을 사용하더라도 묵시적 형변환이 수행되어 문제가 없지만 INT_VARCHAR 의 경우 조회값으로 정수를 사용할 경우 묵시적 형변환이 수행되지 않는 것이다.
Dto, Vo, Entity를 정확히 구분하는 환경에서는 이런 문제를 걱정하지 않아도 되겠지만 통합해서 사용하는 곳 이 점을 유의해야 한다.
'Backend > Database' 카테고리의 다른 글
Mysql 이모지 저장하기 (0) | 2022.02.07 |
---|---|
Mysql DB 용량 확인 (0) | 2022.01.05 |
스키마와 유저. 그리고 데이터베이스 (0) | 2021.08.19 |
mysql 숫자 타입 정의시 괄호 안에 숫자의 의미 (0) | 2021.07.05 |
mysql object 확인 (0) | 2021.03.19 |