가나다 검색시 느려짐 현상 문제입니다. 1 2 3,591

by 콩이 [DB 모델링/설계] 성능 속도 [2012.11.07 17:28:28]


안녕하세요. 한가지 문제가 더 있어 올려봅니다.
문제는 가나다라 검색이 되어야 합니다. 초성 검색이 되어야 하는데, 
검색시 상당히 느립니다..

테이블 구조는 아래와 같습니다.
'그룹' 테이블 
번호 | 그룹명 | 등록자ID | 날짜
'그룹상세' 테이블 - 500만건 데이터 존재(실제 운영에선 2000~3000만건 예상)
번호 | 부모번호 | 성명 | 핸드폰 | 이메일 | 팩스 | 등록자ID | 날짜
'그룹' 테이블은 T_ADDR_GROUP
'그룹상세' 테이블은 T_ADDR_DETAIL 입니다.
인덱스 정보는 아래와 같습니다.
T_ADDR_GROUP (NO) *PK
T_ADDR_GROUP01 (NAME, NO)
T_ADDR_DETAIL (NO) *PK
T_ADDR_DETAIL01 (USER_ID, NO, PARENT_NO)
T_ADDR_DETAIL02 (USER_ID, NO, NAME, PARENT_NO)

T_ADDR_DETAIL02를 새로 추가했습니다. 아무래도 NAME을 검색하다보니..


검색 쿼리는 아래와 같습니다.

카운트시 쿼리
SELECT /*+ INDEX_DESC(PK_T_ADDR_DETAIL02) */ COUNT(NO) AS CNT FROM T_ADDR_DETAIL  WHERE USER_ID = 'lee9982'  AND NAME BETWEEN NCHR(45208) AND NCHR(45795)

카운트 실행계획
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Operation                                 |        Object Name        | Rows | Bytes | Cost | Object Node | In/Out | PStart | PStop | Access Predicates |                                   Filter Predicates                                   |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SELECT STATEMENT Optimizer Mode=ALL_ROWS |                           |    1 |    16 | 6548 |             |        |        |       |                   |                                                                                       |
|  SORT AGGREGATE                          |                           |    1 |    16 |      |             |        |        |       |                   |                                                                                       |
|   INDEX FAST FULL SCAN                   |IN_T_ADDR_DETAIL02  |  7 K | 109 K | 6548 |             |        |        |       |                   | "USER_ID"='lee9982' AND SYS_OP_C2C("NAME")>=U'\B098' AND SYS_OP_C2C("NAME")<=U'\B2E3' |
페이징 리스트 쿼리
SELECT a.name AS GROUP_NAME, b.*    FROM T_ADDR_GROUP A, (SELECT /*+ LEADING(a) USE_NL(b) INDEX(b in_t_addr_detail02) */      
    ROWNUM AS RNUM, b.* FROM T_ADDR_DETAIL B WHERE b.USER_ID = 'lee9982'   AND B.NAME BETWEEN NCHR(45208) AND NCHR(45795) 
    AND ROWNUM <= 10       )b    WHERE a.NO = b.PARENT_NO AND RNUM >= 1 ORDER BY b.NO DESC
    
페이징 리스트 실행계획
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Operation                                 |        Object Name        | Rows | Bytes | Cost | Object Node | In/Out | PStart | PStop |     Access Predicates    |                           Filter Predicates                           |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SELECT STATEMENT Optimizer Mode=ALL_ROWS |                           |   10 |   1 K |   26 |             |        |        |       |                          |                                                                       |
|  SORT ORDER BY                           |                           |   10 |   1 K |   26 |             |        |        |       |                          |                                                                       |
|   HASH JOIN                              |                           |   10 |   1 K |   25 |             |        |        |       | "A"."NO"="B"."PARENT_NO" |                                                                       |
|    VIEW                                  |                           |   10 |   1 K |   23 |             |        |        |       |                          |                                                             "RNUM">=1 |
|     COUNT STOPKEY                        |                           |      |       |      |             |        |        |       |                          |                                                            ROWNUM<=10 |
|      TABLE ACCESS BY INDEX ROWID         |ITHOPE.T_ADDR_DETAIL       |   10 |   460 |   23 |             |        |        |       |                          |                                                                       |
|       INDEX RANGE SCAN                   |.IN_T_ADDR_DETAIL02  |  7 K |       |   22 |             |        |        |       |  "B"."USER_ID"='lee9982' | SYS_OP_C2C("B"."NAME")>=U'\B098' AND SYS_OP_C2C("B"."NAME")<=U'\B2E3' |
|    INDEX FULL SCAN                       |ITHOPE.IN_T_ADDR_GROUP01   |   12 |   168 |    1 |             |        |        |       |                          |                                                                       |
by 마농 [2012.11.07 18:53:38]

일단 힌트를 빼세요...
힌트의 의미를 모르는 상태에서 아무거나 가져다 쓰시면 안됩니다.
페이징 쿼리시 사용한 힌트를 카운트 할때 그대로 쓰시면 안되구요.


페이징 쿼리에 정렬이 안되고 있네요.
정렬하고 페이징해야 하는데 정렬도 안하고 페이징한후 결과만 정렬하네요.
힌트도 전혀 엉뚱하구요. 다른데서나 사용될 힌트를 여기다 넣으셨네요.


T_ADDR_DETAIL02 (USER_ID, NO, NAME, PARENT_NO)
인덱스를 사용하는데... no 에 대한 조건이 없습니다.
user_id 로는 인덱스 스캔 범위를 줄여주지만
name 조건은 인덱스 스캔 범위를 줄여주지 못하고 필터링 하는 역할 밖에 못합니다.
중간의 no 조건이 없기 때문이구요.
T_ADDR_DETAIL02 (USER_ID, NAME, 으로 시작하는 인덱스가 필요한데......


by 콩이 [2012.11.08 15:52:15]
네~ 제가 잘 모르다 보니.. 죄송합니다. 일단 USER_ID, NAME 으로 인덱스를 만들고 테스트를 해보겠습니다. 감사합니다. 마농님..
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입