2014-07-16 2 views
0

나는 쿼리 작업을하고 있었고 oracle sql 개발자를 사용하여 실제로 어떻게해야 할 지 잘 모르는 도움이되는보기를 만들었다.Oracle SQL Query보기에서 실제로 느리지 만 실제 테이블에서는 느리지 않습니까?

데이터베이스의 열이 필요하지 않으며 일부 경우 행이 NULL이거나 잘못된 메모가 기록되어 있기 때문에 기본적으로보기를 만들었습니다. 이 행에는 'Reebok에 대한 조정'과 같은 메모가 포함 된 '텍스트'열이 포함됩니다. 제대로 쿼리를 실행하려면 각 행을 'CUSTOMER_NO'값에 매핑 할 수 있어야했습니다.

여기.

SELECT t.*, 
CASE 
    WHEN LENGTH(CUSTOMER_NO) != '6' and text like '%Nike%' or CUSTOMER_NO IS NULL and text like '%Nike%' THEN 'NIK001' 
    WHEN LENGTH(CUSTOMER_NO) != '6' and text like '%Nike%' or CUSTOMER_NO IS NULL and text like '%Reebok%' THEN 'REB001' 
    ELSE CUSTOMER_NO 
    END as CUSTOMER_NO_ADJUSTED 
FROM 
gen_led_voucher_row_tab t 

그래서이 뷰가 기본적으로 새 열이 'CUSTOMER_NO_ADJUSTED'지금 채워 100 % 인 열이 추가 된보기입니다 내가가 예상대로 좋은 작품.

그러나이 뷰에서 원래 쿼리를 실행하면 계속 실행되고 끝나고/행을 가져 오지 않습니다. 10 분 동안 아무 것도하지 못하게했습니다. 테이블 자체에서 비슷한 쿼리를 실행하면 30 초 이내에 데이터를 얻을 수 있습니다.

다음은 실행하려는 쿼리입니다. 기본적으로 부서 이름에 CODE_D 값을 그룹화하고 'EXISTS'옵션을 사용하여 쿼리를 한 번 실행하면 누가 기존 고객인지 (XXX 개월 만에 비즈니스를 수행 한 적이 있는지) 'NOT EXISTS'로 다시 실행합니다. 이론적으로 새로운 비즈니스 만의 부서 가치를 창출 할 것입니다 (지정된 달에 우리와 거래하지 않은 고객).

SELECT 
/* CASE statement to rename CODE_D product lines to what the product is. List was provided by accounting in June of 2014 */ 

CASE 
     WHEN CODE_D = '11' or CODE_D = '12' or CODE_D = '18' or CODE_D IS NULL THEN 'Laces' 
    WHEN CODE_D = '15' or CODE_D = '16' or CODE_D = '40' or CODE_D = '45' or CODE_D = '50' 
     or CODE_D = '55' or CODE_D = '60' or CODE_D = '65' or CODE_D = '67' or CODE_D = '30' 
     or CODE_D = '35' THEN 'Custom Soles' 
    WHEN CODE_D = '17' THEN 'Custom Heels' 
    WHEN CODE_D = '19' or CODE_D = '39' or CODE_D = '49' or CODE_D = '59' or CODE_D = '69' 
     THEN 'Socks' 
    WHEN CODE_D = '14' THEN 'Sneakers' 
    WHEN CODE_D = '89' THEN 'Dress Shoes' 
    WHEN CODE_D = '99' THEN 'Other' 
    ELSE 'UNKNOWN' 
    END as DEPARTMENT, 
sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL 
FROM 
KPIC_MIKE_METRIC1 a 
where ACCOUNTING_YEAR like '2014' 
and ACCOUNT not like '4010' 
and ACCOUNT like '4%' 



and Exists 
(
    Select * 
    From KPIC_MIKE_METRIC1 b 
    where voucher_date >= '01-FEB-13' 
    and  voucher_date < '01-FEB-14' 
    and ACCOUNT not like '4010' 
    and ACCOUNT like '4%' 
    and  (credit_amount > '1' or debet_amount > '1') 
    and  a.CUSTOMER_NO_ADJUSTED = b.CUSTOMER_NO_ADJUSTED 
) 



GROUP BY 
/* 
This GROUP BY statement needs to contain an entire copy of the CASE statement, minus the alias. 
If changes are made to the CASE statement please update this GROUP BY statement 
*/ 
CASE 
      WHEN CODE_D = '11' or CODE_D = '12' or CODE_D = '18' or CODE_D IS NULL THEN 'Laces' 
    WHEN CODE_D = '15' or CODE_D = '16' or CODE_D = '40' or CODE_D = '45' or CODE_D = '50' 
     or CODE_D = '55' or CODE_D = '60' or CODE_D = '65' or CODE_D = '67' or CODE_D = '30' 
     or CODE_D = '35' THEN 'Custom Soles' 
    WHEN CODE_D = '17' THEN 'Custom Heels' 
    WHEN CODE_D = '19' or CODE_D = '39' or CODE_D = '49' or CODE_D = '59' or CODE_D = '69' 
     THEN 'Socks' 
    WHEN CODE_D = '14' THEN 'Sneakers' 
    WHEN CODE_D = '89' THEN 'Dress Shoes' 
    WHEN CODE_D = '99' THEN 'Other' 
    ELSE 'UNKNOWN' 
    END 
ORDER BY TOTAL DESC 

어떤 도움을 주시면 감사하겠습니다. 나는 초보자이며 여기에서 제대로 실행하는 방법에 대한 조언을 얻을 수있을 것이라고 확신합니다. 어떤 도움을 주셔서 감사합니다!

+0

실행 계획은 무엇을 말하는가를 DEPT_CODES? –

답변

1

당신은보기 KPIC_MIKE_METRIC1에서 선택하고 또한 당신이 시작할 때 와일드 카드와 가진 LIKE 조건 케이스로 구성하여 계산 된 필드는 필드 CUSTOMER_NO_ADJUSTED를 비교 같은보기 상 exists 절을 추가 조건의 끝 (따라서 색인을 사용하지 않음).

이 테이블에 많은 수의 행이 들어 있으면 성능이 저조하지 않습니다.

나는 정보를 테이블에 저장하여 부서에 대한 코드 매핑을 해결할 것입니다. 최소한보기를 더 읽기 쉽고 유지 보수 할 수있게 만들고 코드와 부서를 더 쉽게 추가 할 수 있습니다.

성능을 위해 임시 테이블을 사용할 수도 있지만 주로 @mrjoltcola와 같은 결정 론적 기능에 익숙하지 않기 때문입니다. :)

+0

+1 - 실제로 코드를 부서에 매핑하는 것이 더 바람직합니다. CASE 문을 전혀 사용할 필요가 없습니다. – codenheim

+0

뷰 대신 임시 테이블을 생성하면 모든 문제가 해결되었습니다! 솔루션을 가져 주셔서 감사합니다! @mrjoltcola 덕분에 의견을 보내 주셔서 매우 도움이되었습니다. – Mike

1

내가해야 할 첫 번째 일은 주소 CUSTOMER_NO_ADJUSTED입니다. case 문에서 계산 된 열을 생성 한 다음 JOIN 열로 사용하면 많은 성능을 발휘하지 못합니다.

당신이 보여준 방식대로 사용하려는 경우 목표는 어떻게하면 해당 열의 조인과 조건에 인덱스를 적용해야합니다.

  1. DETERMINISTIC 함수 내의 CUSTOMER_NO_ADJUSTED 열 뒤에 CASE 논리를 래핑 한 다음 해당 함수에 함수 기 반 색인을 작성할 수 있습니다. DETERMINISTIC은 동일한 입력에 대해 함수가 항상 동일한 출력을 리턴한다는 것을 Oracle에 알리는 방법 일뿐입니다. 그렇게하면 오라클이 색인을 생성 할 수 있습니다. 이 키워드가 없으면 오라클은 함수 기반 인덱스를 생성하는 것을 거부합니다.
  2. 또는 더 전통적인 접근법 - CUSTOMER_NO_ADJUSTED를 INSERT 또는 UPDATE 트리거로 채워진 실제 열로 만든 다음 간단한 인덱스로 해당 열을 인덱싱 할 수 있습니다.

후자는 더 직관적이며 직관적 (및 휴대용)입니다.

업데이트 : 당신의 CASE 문을 읽은 후, 난 당신이 더 나은 것 같아요 제공 부서 조회 테이블로 변환하고

create table departments (
    id int primary key, 
    name varchar(50) 
); 

insert into departments values(1, 'Laces'); 
insert into departments values(2, 'Custom Soles'); 
insert into departments values(3, 'Custom Heels'); 
insert into departments values(4, 'Socks'); 

create table dept_codes (
    code_d varchar(2) primary key, 
    dept_id int 
); 

insert into dept_codes values('11', 1); -- Laces 
insert into dept_codes values('12', 1); 
insert into dept_codes values('18', 1); 
insert into dept_codes values('15', 2); -- Custom Soles 
insert into dept_codes values('16', 2); 
insert into dept_codes values('40', 2); 
insert into dept_codes values('45', 2); 
insert into dept_codes values('50', 2); 
insert into dept_codes values('17', 3); -- Custom Heels 
insert into dept_codes values('19', 4); -- Socks 
insert into dept_codes values('39', 4); 
+0

와우 @EvilTeach 내 글을 편집하는 데 약간의 시간이 걸렸습니다. 중요한 편집을 잃었습니다. – codenheim

+0

흥미 롭습니다. 죄송합니다. – EvilTeach

+0

다른 답변에 대한 답변을 편집 해 주셔서 감사합니다. 정말 테이블을 만들거나 열을 추가하고 싶지 않습니다. 우리의 지원 공급자는 우리와의 지원 계약을 깨뜨리는 것에 대해 정말로 까다롭기 때문에 내가해야 할 마지막 일은 필요할 때 언제든지 되돌아 갈 수있는 변명 거리를 제공하는 것입니다. 임시 테이블로 사용해 볼 수도 있습니다. – Mike

관련 문제