일단 문제는 https://gall.dcinside.com/mgallery/board/view/?id=backend&no=20979 이 문제고
정답은
SELECT*
FROM 고객
WHERE 가입일자 Between '201001' and '201012'
AND 고객 등급 In ('A', 'B') 임
가볍게 설명하자면 Between 부분을 -> IN
Like 부분을 -> Between 방식으로 바꿔야함
내가 설명하고 싶은 부분은 Like임(나도 Like를 쓰면 안된다~만 기억나서 책보고 다시 공부함)
CASE1) WHERE 고객등급 = 'B' And 가입일자 Like '2010%' vs WHERE 고객등급='B' 가입일자 Between '201001' and '201012' 는 서로 다름
결과적으로 데이터는 같겠지만 인덱스 스캔량이 차이가 날수 있음.(무조건 차이가 나는거는 아님)
만약 데이터 분포가 그림 3-41와 같이 되어있으면(날짜는 좀 틀린데 이정도는 이해할거라 믿음) Like는 '201000'도 저장돼 있을 수 있기 때문에 B부터 바로 읽을 수 없음
반면 Between은 효율적으로 읽을 수 있음 고객등급 A를 읽는 케이스도 있음
CASE2) WHERE 고객등급 = 'A' And 가입일자 Like '2010%' vs WHERE 고객등급='A' 가입일자 Between '201001' and '201012' 도 서로 다름
이것도 위와 동일하게 Between 쿼리는 스캔 종료 시점이 'B'인 첫 레코드에서 바로 종료할 수 있는데 Like 쿼리는 201013이 있을까봐 고객등급 'B'인 데이터까지 전부 다 스캔 후 종료할 수 있음
이 와 같은 사례때문에 날짜는 Between 쿼리를 사용하는게 좋음(가독성 측면에서도 더 좋고)
Q: Like는 내부적으로 캐스팅이 일어나기 인덱스를 못타는거 아니냐?
A: DBMS 마다 다름 어떤 디비는 암묵적으로 캐스팅하고 어떤 디비는 명시적으로 캐스팅 해야 하는 디비가 있음 근데 위의 문제는 오라클 기준으로 인덱스를 탈수있음
오라클 기준으로 문자열 vs 숫자형이 만나면 숫자형이 이기고 문자열 vs 날짜형이 날짜형이 이김 따라서 위에서 조건절 문자열이 -> 날짜형으로 캐스팅 되기 때문에
인덱스를 탈수있음
굿
근데 위에서는 다 문자형아님? 월단위로 끊는거같은데
추가로 like에서 숫자 vs 문자면 문자로 캐스팅
아 빠진부분 설명 ㄱㅅ
본문 Qestion은
https://gall.dcinside.com/mgallery/board/view/?id=backend&no=20979
여기 부분 헛소리에 답변을 한거야
근데 생각해보면 like는 문자아니면 안쓰는게 나을거같기도하고
가독성 측면에서도 그게 좋지 옵션처리 할거아니면
문자아니여도 like 사용할때가 있다고한건 select * from 고객 where 가입일자 like :일자 || '%' 이런식으로 동적쿼리 만들때 필요하다고 말한거였는데 헷갈리네
다시 정리하면 Like 없이 만나면 숫자로 캐스팅 Like에서는 문자로 캐스팅 ㅇㅅㅇ
예제는 어디서 퍼왔노?
사진은 친절한 내용임 글로만 설명하기 빡세서 구글링 해서 퍼옴 ㅇㅅㅇ
정성추
이거 예전에 알려준 인덱스 스킵 스캔이랑 비슷한 느낌이네 옵티마이저는 뭐가 있는지 모르니까 더 넓은 범위로 스캔
왜 유익하노 - dc App