1

먼저 사용하지 : 나는 질문이 사소한 경우 너무 탐닉하시기 바랍니다하는 DB 전문가가 아니에요 ...파이어 버드 2.5 SQL 쿼리 실행 계획과 인덱스 OR 문

을 나는 찾고 자식 테이블 CHILD에 대한 쿼리를 항목이로드 될지 여부를 판별하기 위해 마스터 테이블 PARENT의 일부 값을 올리십시오.

쿼리는이

SELECT C.*, P.DATE, P.STATUS 
FROM CHILD C, PARENT P 
WHERE C.PARENT_ID = P.ID 
AND (P.DATE > '01.01.2015' OR (P.STATUS <> 1 AND P.STATUS <> 9)); 

처럼 나는 내가 비 인접 선택해야하는 상태 값과 같은 불평등을 사용할 필요가 있음을 강조하기 위해 일부러 STATUS 값을 선택한 보인다.

CHILD.PARENT_ID 필드에 외래 키가 PARENT.ID이고 CHILD.PARENT_ID에 색인이 생성되었습니다. 또한 DATESTATUS 필드에 PARENT 테이블의 색인을 생성했습니다. 내가 가진 ORANDCHILDPARENT_IDPARENT에 인덱스를 사용하는 대신 이제

, 나는 무엇을 기대했다 DATE, STATUS에 인덱스를 사용합니다.

그러나 OR을 사용하는 경우 쿼리는 CHILD의 자연 계획과 PARENT.ID의 기본 키 인덱스를 사용합니다.

SELECT P.* FROM PARENT P WHERE (P.DATE > '01.01.2015' OR (P.STATUS <> 1 AND P.STATUS <> 9)); 

자연의 계획보다 더 나은 사용하는 이러한 쿼리를 최적화 할 수있는 방법이 있나요 ?? : 난 단지 부모 테이블에 쿼리를 적용하는 경우 동일

가 발생합니다

+0

여기에서 두 가지 계획을 업데이트 할 수 있습니까? Lhttps : //www.brentozar.com/pastetheplan/ ..또한 테이블 개수, 두 테이블의 인덱스 – TheGameiswar

+0

사용중인 데이터베이스에 태그하십시오. –

+0

질문을 편집 해주십시오. (모든 인덱스 포함) 테이블과 실행 계획에 대한'create table' 문을 추가하십시오. [_Formatted_] (http://stackoverflow.com/help/formatting) ** 텍스트 **하시기 바랍니다. [스크린 샷 없음] (http://meta.stackoverflow.com/questions/285551/why-may-i-not -upload-images-of-code-on-so-ask-a-question/285557 # 285557) –

답변

2

'또는'을 쓰면 모든 P.DATE가 히트 일 수 있습니다. 또한 모든 P.STATUS는 히트 수 있습니다. 인덱스를 사용하려면 매우 좋은 전제 조건이 아닙니다.

여기에서 시스템을 지원하고 두 가지 질문을하고이를 UNION과 연결해야합니다. Like

SELECT C.*, P.DATE, P.STATUS 
    FROM CHILD C, PARENT P 
WHERE C.PARENT_ID = P.ID 
    AND P.DATE > '01.01.2015' 
UNION 
SELECT C.*, P.DATE, P.STATUS 
    FROM CHILD C, PARENT P 
WHERE C.PARENT_ID = P.ID 
    AND P.STATUS <> 1 
    AND P.STATUS <> 9; 

참고 : 대부분의 P.STATUS 값이 1과 같지 않고 9가 아니면 성능이 저하됩니다. 'and'라는 단어에 대한 모든 단어가 색인 된 책을보고 있다고 상상해보십시오. 모든 페이지에 표시됩니다. 책을 순차적으로 읽는 것이 색인을 사용하는 것보다 빠를 것입니다.

2

이렇게하면 인덱스에서 인덱스를 사용하는 것이 매우 어려울 수 있습니다. 첫째, join의를 사용하여 쿼리를 다시 작성 :

SELECT C.*, P.DATE, P.STATUS 
FROM CHILD C JOIN 
    PARENT P 
    ON C.PARENT_ID = P.ID 
WHERE P.DATE > '2015-01-01' OR P.STATUS NOT IN (1, 9); 

는이 UNION ALL를 사용하여 다시 작성할 수 있습니다 :

SELECT C.*, P.DATE, P.STATUS 
FROM CHILD C JOIN 
    PARENT P 
    ON C.PARENT_ID = P.ID 
WHERE P.DATE > '2015-01-01' 
UNION ALL 
SELECT C.*, P.DATE, P.STATUS 
FROM CHILD C JOIN 
    PARENT P 
    ON C.PARENT_ID = P.ID 
WHERE P.DATE <= '2015-01-01' AND -- This condition prevents overlaps 
     P.STATUS NOT IN (1, 9); 

하위 쿼리 지금 PARENT(DATE, ID)PARENT(STATUS, DATE, ID)에 인덱스를 사용할 수있다.

그러나 결과를 필터링하면 실제로 쿼리가 빨라지는 것은 확실하지 않습니다. 필터가 얼마나 선택적인지에 달려 있습니다.