어떤 많인 데이터가 담긴 테이블에서 다중아이템을 검색할려 합니다 0 8 500

by 메로나 [2020.05.27 00:25:51]


A라는 테이블에 데이터가 꽤 많이 있습니다.

여기에서 item값이 없다면 기간에 대해서 데이터를 뽑아오고, item값이 존재한다면 해당 item에 대해서 조회해 오려고 합니다. 인덱스가 분리 되어야되는데요

SELECT 
    * 
FROM A 
WHERE 1=1
    AND 
    (
        ( 
          p_item IS NULL
          AND create_date >= p_from AND create_date < p_to
        )
        OR
        (
            p_item IS NOT NULL
            AND item = p_item
        )
    )

 

그런데 여기서 문제가 되는게 있는데요 p_item이 1개면 저렇게 = 로 하면 데이터가 빨리나오는데요

그게 아니고 파라미터로 넘어온 p_item이 , 기반으로 된 것이라면

p_item = '거위,오리,강아지,닭'

 

이런식이면 , 단위로 구분하여 4개의 item이 조회되어야 되는데요

 

SELECT 
    * 
FROM A 
WHERE 1=1
    AND 
    (
        ( 
          p_item IS NULL
          AND create_date >= p_from AND create_date < p_to
        )
        OR
        (
            p_item IS NOT NULL
            AND item IN (
                            SELECT 
                                REGEXP_SUBSTR(p_item, '[^,]+', 1, LEVEL) TXT
                            FROM DUAL
                            CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(p_item, '[^,]+',''))+1
                        )

        )
    )

 

이렇게 REGEXP_STR()을 사용하여 , 구분자 단위로 행을 만들어서 item이 있는지 IN 절을 썼는데요

너무 느립니다....

방법이 없을까요? 인덱스 구분할려고 하다가 여기까지 와버렸네요 ㅠㅠ 하나 해결할 듯 싶으면 또 하나가 문제 되고

여드름 같이 ㅠㅠ

 

 

by 마농 [2020.05.27 09:50:11]

/*+ USE_CONCAT */ 힌트 써보시고
그래도 안되면 UNION ALL 로 쿼리 분리하세요.


by 메로나 [2020.05.27 10:37:33]

/*+ USE_CONCAT */를 SELECT 절에 썼는데요

SELECT 
   /*+ USE_CONCAT */ t.* 
FROM A t
WHERE 1=1
    AND 
    (
        ( 
          p_item IS NULL
          AND t.create_date >= p_from AND t.create_date < p_to
        )
        OR
        (
            p_item IS NOT NULL
            AND t.item IN (
                            SELECT 
                                REGEXP_SUBSTR(p_item, '[^,]+', 1, LEVEL) TXT
                            FROM DUAL
                            CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(p_item, '[^,]+',''))+1
                        )

        )
    )
 

역시나 p_item이 존재할 시에 조회하면 느립니다. 이래 저래 해보고 있는데요 마농님~

저기 조건에

            AND t.item IN (
                            SELECT 
                                REGEXP_SUBSTR(p_item, '[^,]+', 1, LEVEL) TXT
                            FROM DUAL
                            CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(p_item, '[^,]+',''))+1
                        )

이부분을 하드코딩으로

    AND t.item IN ('거위', '오리', '강아지', '닭')

이렇게 하면 바로 조회가 되어버립니다.

그런데

            AND t.item IN (
                            SELECT 
                                REGEXP_SUBSTR('거위,오리,강아지,닭', '[^,]+', 1, LEVEL) TXT
                            FROM DUAL
                            CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('거위,오리,강아지,닭', '[^,]+',''))+1
                        )

이렇게 하면 너무 오래걸려버립니다.

안에 

                            SELECT 
                                REGEXP_SUBSTR('거위,오리,강아지,닭', '[^,]+', 1, LEVEL) TXT
                            FROM DUAL
                            CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('거위,오리,강아지,닭', '[^,]+',''))+1
 

이부분만 따로 조회하면 또 빨리 나오구요

A 테이블은 엄청 데이터가 많습니다

Index는 item, create_date 가 인덱스 걸려 있습니다


by 버드나무 [2020.05.27 14:35:16]

AND t.item IN (  p_item )

이렇게 써도 될꺼 같은데요;;;


by 메로나 [2020.05.27 15:36:56]

p_item의 데이터가  여러개일경우

p_item = 'A,B,C,D'

이런식의 데이터 입니다. 그래서 REGEXP_SUBSTR()로 A B C D를 콤마 , 로 분리해서 IN 조건에 넣었습니다


by 버드나무 [2020.05.27 15:51:03]

p_item 이 변수라고 가정하고 자바에서 값을 조금 수정해서 던지시면 

ex)

String p_item = "";
String str = "거위,오리,강아지,닭";
String arr = str.split(",");
for(int i=0; arr.length; i++){
    if("".equals(p_item)){
        p_item = arr[i];
    }else{
        p_item = p_item + "," + arr[i];
    }
}

이렇게...


by 메로나 [2020.05.27 16:03:52]

죄송한데요 방금 위에 답주신 자바소스가 결국 다시 문자열 합치는거 아닌가요?

p_item = "거위,오리,강아지,닭";

 


by 버드나무 [2020.05.27 16:34:06]

아 착각요 죄송요;;

 

 

String p_item = "";
        String str = "거위,오리,강아지,닭";
        String[] arr = str.split(",");
        for(int i=0; i<arr.length; i++){
            if("".equals(p_item)){
                p_item = "'"+arr[i] +"'";
            }else{
                p_item = p_item + ", '" + arr[i] +"'";
            }
        }
        
        System.out.println("p_item ="+p_item);

 

 

결과값 : p_item ='거위', '오리', '강아지', '닭'


by 메로나 [2020.05.28 12:00:32]

p_item 이  'A','B','C'

이렇게 된거라면 패키지 호출 때 어떻게 인자를 넣을 수 있나요???

 

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입