그림 4-4는 소속 회사의 전자공시 서비스의 펀드공시 검색 화면 펀드 검색 조건이 다. 사용자가 ‘펀드명’ 조건을 선택할 경우 우측의 텍스트 인풋 박스에는 펀드명 중 일부를 입력하게 되고 ‘펀드선택’ 조건을 선택할 경우는 펀드를 조회하는 다른 화 면을 제공하여 최종적으로는 펀드 코드를 입력받는다.
이 경우 사용자의 선택에 따 라 조건의 컬럼이 변경되므로 개발자는 바인드 변수를 사용하지 않고 참고 4-17 과 같이 사용자의 선택에 따라 서로 다른 컬럼을 사용자의 입력값과 함께 리터럴 (Literal)하게 구성하여 SQL을 결합하는 방식을 채택했다
이와 같은 구성은 개발 이 편리할지는 몰라도 리터럴하게 구성한 부분은 말 그대로 정해진 값이므로 리터 럴로 구성될 종류만큼 해당 SQL은 모두 다른 SQL로 DBMS는 인식하게 된다.
특 히 이 화면의 경우 사용자가 입력할 펀드명의 형식과 종류의 예측이 불가능할 만큼 다양한 종류의 입력값이 존재할 것이고 그 만큼 다양한 SQL이 존재할 것이므로 옵 티마이저가 새로운 SQL을 파싱하는 하드파싱에 의한 성능저하주5)가 발생을 했었다 (물론 최대한 소프트 파싱하려고 다양한 알고리즘이 티베로에 적용되어 있겠지만 일정 부분 하드파싱을 피할 수 없을 것이고 그것이 성능저하의 원인이 되었다).
| 주5 | ...(중략) 이렇게 최적으로 만들어진 SQL 플랜은 LIBRARY CACHE에 등록되어 같은 SQL에 대한 수행 요청 시
에 재활용되어 OPTIMIZER 단계를 건너뛰고 SQL을 수행하게 된다. 앞의 OPTIMIZER 단계를 거치는 PARSING
을 HARD PARSING이라 하고, OPTIMIZER 단계를 건너뛰고 LIBRARY CACHE에서 해당 플랜을 가져오는
PARSING을 SOFT PARSING이라고 부른다.
(출처 : Tibero Optimizer SQL Execution Plan, http://technet.tmaxsoft.com)
if(입력클래스.사용자선택값() == null || 입력클래스.사용자선택값().equals("")) { //do nothing } else { if( 입력클래스.사용자선택조건().equals("펀드선택")) { codeStr += " AND 상품정보테이블.상품코드 IN (" + 입력클래스.사용자선택값() + ")"; } else if( 입력클래스.사용자선택조건().equals("펀드명")) { codeStr += " AND ( '" + 입력클래스.사용자선택값() + "' is null or UPPER(REPLACE(TRIM(상품정보테이블.상품명),' ','')) LIKE '%'|| UPPER(REPLACE(TRIM( '" + 입력클래스.사용자선택값()() + "' ),' ','')) ||'%')"; } } whereSql = new String(기본str+비교Str + codeStr); > 위 string은 각 조건에 따라 다음과 같은 SQL 형태로 결합된다. 따라서 사용자의 입력값에 따라 티베로에서 모드 다른 SQL로 인식하여 하드파싱할 가능성이 존재한다 1-1) 펀드 선택의 경우 : AND 상품정보테이블.상품코드 IN ('1234','5678','abcd','efgh') 1-2) 펀드명의 경우 : AND ( '입력값' IS NULL OR UPPER ( REPLACE (TRIM (상품정보테이블.상품명), '', '')) LIKE '%' || UPPER ( REPLACE ( TRIM ( '입력값'), ' ', '')) || '%')
그렇다면 어떻게 해야 하드파싱의 부하를 피할 수 있을까? 많은 성능 관련 서적에서 강조하고 있듯이 바인드 변수를 사용하면 된다.
위와 같이 검색 조건이 다소 복 잡하여 바인드 변수를 사용할 방법이 없다고 판단되는 것도 조금만 생각을 해보면 가능하다. 소속 회사는 다음과 같이 해당 조건을 구성하여 원본 쿼리에 추가, 리터 럴 구성을 제거하여 문제를 해결할 수 있었다.
AND( ( :사용자선택조건 = '펀드명' and ( :사용자선택값 IS NULL OR UPPER (REPLACE (TRIM(상품정보테이블.상품명), ' ', '')) LIKE '%' || UPPER (REPLACE (TRIM ( :사용자선택값), ' ', '')) || '%' )) OR ( :사용자선택조건 = '펀드선택' and (:사용자선택값 IS NULL OR INSTR(:사용자선택값, 상품정보테이블.상품코드_CD) >0))
- 강좌 URL : http://www.gurubee.net/lecture/4134
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.