Backend/Database

인덱스 스캔과 묵시적 형변환

findmypiece 2021. 10. 20. 11:35
728x90

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를 정확히 구분하는 환경에서는 이런 문제를 걱정하지 않아도 되겠지만 통합해서 사용하는 곳 이 점을 유의해야 한다.

728x90

'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