어떤 블로그에 정리가 잘 되어 있어서 가져왔습니다..
저는 현재 SELECT문을 IN절에 바로 넣어주는 방식을 사용하고 있는데요. 블로그를 찾아보면 이런 방식은 잘 사용을 안 하는 것 같아요..
일곱가지 방법 중 어떤 게 속도가 빠르고 덜 무리가 가는 방법인가요? 신입이라 잘 모르겠네요..
데이터가 많습니다 ㅠㅠ
추천 부탁드립니다.
제가 사용하는 방법
EX)
SELECT DISTINCT NAME
FROM NAMETABLE
을 치면 NAME 목록이 쫙 뜹니다.
김순이
김철수
김훈이
이짱구
.
.
.
.
최종적으로 구하고 싶은 쿼리문에
SELECT *
FROM ALLTABLE
WHERE
ALLTABLE.NAME IN (
SELECT DISTINCT NAME
FROM NAMETABLE
)
AND AGE IN (?,?,?,?,?)
7가지 방법
1) 쿼리를 union 방식으로 하여 사용한다.
in조건에 들어갈 값들이 1000개이상일 경우에는 쪼개어서 조회한 뒤 union을 사용하여 결과값을 합치는 방식인데요..
사실 이 방식은 union을 쓰게되면서 조회대상 테이블을 여러 번 스캔하게 되어 불필요한 io발생이 이뤄질 것 같아 보여 좋은 방법은 아닌 것 같습니다.
2) in조건을 다중 조건으로 수행시킨다.
조건절이 아래와 같이 들어갈 경우 ORA-01795오류가 발생하게 되는 반면..
where column1 in ('1','2'....'1003','1004')
아래와 같이 들어갈 경우에는 정상 수행됨을 확인할 수 있었습니다.
where ('0',column1) in(('0','1'),('0','1')....('0','1003'),('0','1004'))
3) 연속되는 값이 in조건으로 들어가게 된다면 in보다는 between을 사용한다.
where column1 betwen 1 and 1004 와 같이 넣게 되면 범위연산이 이뤄지면서 정상 수행이 가능하기 때문입니다.
4) 임시테이블 같은 것을 만들어서 exists혹은 join연산을 통해서 처리한다.
exists나 join의 경우 갯수에 따른 제약조건이 없어 매우 좋은 처리이긴 할 것으로 생각하나,
데이터를 임시테이블에 넣고 지우고 작업을 추가적으로 진행되어야하는 불편함도 있어보입니다.
5) global temporary table 사용하기
임시테이블과 비슷하지만 오라클에서 제공하는 기능으로 세션별로 생성되는 global temporary table 을 생성하여 해결 할 수도 있을 것같습니다.
create global temporary table temp(
column1 varchar2(100)
) on commit delete rows;
on commit delete rows옵션을 주면 session이 끝나거나 commit이 됐을 경우 temp테이블에 들어있는 데이터를 자동으로 모두 truncate를 시켜준다고하니
4)방식에서 지우는 작업을 안 해도 되는 장점이 있을 것 같습니다.
다른 옵션을 주어 session이 끝날 때만 지울 수도 있고, 디스크가 아닌 메모리에 올려서도 쓸 수있다고 하네요
6) 오라클에서 제공하는 시스템 함수 사용하기.
서치 중에 알게된 것으로 sys.odcinumberlist, sys.odcivarchar2list 와 같은 함수를 제공한다고합니다.
select * from search_table
where column1 in(select column_value from table(sys.odcivarchar2list('1','2',...'1003','1004')))
와 같이 사용하면 된다고 합니다.
[정리]
제가 알아본 것으로는 위에 정리한 총 7가지(subList포함) 방법으로 ORA-01795를 해결 할 수 있을것 같습니다.
이번 오류는 매우 간단한 쿼리 내에도 이슈 포인트는 숨어있을 수 있다는 것과
사소한 것도 다시 한번 생각해볼 필요성이 있다는 것을 느낄 수 있는 좋은 경험이었습니다.