ORA-01795:ERROR 쿼리 수정 및 해결 방법

ORA-01795:ERROR 쿼리 수정 및 해결 방법

2018, Jun 13    

1. ORA-01795

  • 오라클의 웹 사이트에서 오류를 검색하면 다음과 같습니다.

ORA-01795 :리스트 내의 최대 식은 1000입니다.
원인 : 쿼리의 식 수가 1000 개를 초과했습니다. 사용되지 않는 열 / 식도 계산됩니다. 허용되는 최대 식은 1000 개입니다.
해결법 : 목록의 표현식 수를 줄이고 다시 제출하십시오.


1000 개 이상의 식 또는 IN 절의 리터럴을 사용하려고하면 이 오류가 발생합니다.
column in (‘1′,’2′,…’1200’)
즉, ORACLE의 IN(…) 구문은 999개 이하만 처리 가능하고 1000개 이상일때 에러가 생김.


보통 연산할 데이터의 수가 1000개 미만일때 OR 보다는 IN을 사용하는 이유

1) IN은 서비쿼리를 사용하여 보다 유연한 확장이 가능하다.
2) IN은 반드시 하나의 컬럼이 비교되어야 하므로 나중에 인덱스 구성에 대한 전략을 수립할 때 유리하다.
3) 옵티마이저는 복잡한 OR에 매우 취약하다.


왜 IN 구문에 1000 개 이상의 값이 있었는지?

  • 1000 개 이상의 DB 목록을 조회했을때, ORA-01795 ERROR CODE 발생
  • 사용자가 도움을 요청하는 포럼 게시물에서도 IN 절에는 1 백만 개가 넘는 값이 넘을때의 에러 확인

ORA-01795에 대한 해결 방법

  • 오라클에서는 1000개의 값이 한계이기 때문에 이에 대한 해결 방법이 필요합니다.
    쿼리 실행 방법에 따라 몇 가지 해결 방법이 있습니다.

iBatis Iterate 문법

  • Collection을 반복하거나 리스트내 각각을 위해 몸체부분을 반복

Iterate Attributes

  • prepend - preparedstatement에 붙을 오버라이딩 가능한 SQL 옵션
  • property - 반복되기 위한 java.util.List 타입의 property
  • open - 반복문 전체를 열기 위한 문자열, 괄호를 위한 사용에 유용함
  • close - 반복문 전체를 닫기, 위한 문자열, 괄호를 위한 사용에 유용함
  • conjunction - 각각 반복문 사이에 적용되기 위한 문자열, AND 그리고 OR 사용에 유용함

Dynamic Tag(ADD)

  • 동적 SQL은 iBATIS의 매우 강력한 기능입니다. 때로는 매개 변수 객체의 상태에 따라 WHERE 절을 변경해야합니다.
    이러한 상황에서, iBtis는 SQL의 재사용 성과 유연성을 향상시키기 위해 매핑 된 명령문 내에서 사용할 수 있는 동적 SQL 태그 세트를 제공합니다.

기존 쿼리

<select id="selectTableExistList" parameterClass="commonVO" resultClass="commonVO">
 <![CDATA[
 SELECT table_name FROM tabs
 ]]>
 
 <isNotNull property="table_name">
 where table_name = #table_name#
 </isNotNull>
 
 <isNull property="table_name">
 <iterate property="table_list" prepend=" WHERE table_name IN " open="(" close=")" conjunction=",">
 #table_list[]#
 </iterate>
 ORDER BY table_name asc
 </isNull>
 </select>
[실행]

SELECT table_name

FROM tabs

WHERE table_name IN ( table_list[0], table_list[1], table_list[2]..... ,table_list[999])  데이터 인덱스 값이 1000 이상일때 에러 발생 

ORDER BY table_name asc

변경된 쿼리

<select id="selectTableExistList" parameterClass="commonVO" resultClass="commonVO">
 <![CDATA[
 SELECT table_name FROM tabs
 ]]>
 <dynamic prepend="WHERE">
 <isNotNull property="table_name">
 table_name = #table_name#
 </isNotNull>

<isNull property="table_name">
 <iterate property="table_list" open="(" close=")" conjunction=" OR ">
 table_name = #table_list[]#
 </iterate>
 ORDER BY table_name asc
 </isNull>
 </dynamic>
</select>
[실행]

SELECT table_name

FROM tabs

WHERE

(

table_name = table_list[0]

OR table_name = table_list[1]

OR table_name = table_list[2]

....

)

ORDER BY table_name asc