2013-09-04 9 views
2

직원과 관련된 모든 데이터가 포함 된보기가 있습니다. 약 350k 개의 레코드가 있습니다. 이름 검색 기능을 만들어야합니다. 입력 한 키워드와 일치하는 모든 데이터를 검색합니다.oracle에서 문자열 검색 최적화

쿼리 성능이 매우 느리며 데이터를 검색하는 데 15-20 초가 걸립니다. 비용 15000

내 쿼리 : EMPLOYEE_BASIC_DTLS 이후

SELECT   H.PERSON_ID, 
        B.EMPLOYEE_ID, 
        INITCAP(B.FIRST_NAME) EMP_FNAME, 
        INITCAP(B.MIDDLE_NAME) EMP_MNAME, 
        INITCAP(B.LAST_NAME) EMP_LNAME, 
        B.EMPLOYEE_TYPE PERSON_DESC, 
        B.EMPLOYMENT_STATUS STATUS_TYPE, 
        EA.BASE_BRANCH 

       FROM EMPLOYEE_BASIC_DTLS B, 
        EMP_ASSIGNMENT_DTLS_MV EA, 
        EMPLOYEE_HIS_DEPNDENT_TBL H 
      WHERE B.PERSON_ID = EA.PERSON_ID 
       AND B.PERSON_ID = H.PERSON_ID 
       AND ((UPPER(B.FIRST_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%')) OR 
        (UPPER(B.MIDDLE_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%')) OR 
        (UPPER(B.LAST_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%'))) 
       AND TRUNC(SYSDATE) BETWEEN EA.EFFECTIVE_START_DATE AND 
        EA.EFFECTIVE_END_DATE 
       AND UPPER(H.RELATIONSHIP_CODE) = 'A'; 

내가 색인을 사용하지 못할 전망이다.

+2

모든 표현식에 와일드 카드가 필요합니까? "저스틴 동굴"을 "스틴 (stin)"으로 타이핑 할 때 정말로 원하는 사람들이 있습니까? 주요 와일드 카드는 기본 테이블의 모든 인덱스가 사용되는 것을 방지합니다. 주요 와일드 카드가 정말로 필요하다면 Oracle Text 색인을 사용하고 쿼리를 리팩터링하여 잠재적으로 LIKE가 아닌 CONTAINS를 사용할 수 있지만 그 또한 다소 복잡합니다. –

답변

1

당신이 뷰에 인덱스를 넣을 수없는 사실이지만, 당신은 확실히 기본 테이블에 인덱스를 넣을 수 있습니다. 그러나 @JustinCave에서 언급 한 것처럼 적절한 테이블에 인덱스를 추가하더라도이 쿼리는 LIKE을 사용하기 때문에 여전히 사용하지 않습니다. UPPER 기능은 FIRST_NAME, MIDDLE_NAMELAST_NAME 컬럼에 적용되고 있기 때문에 또한, 함수 기반 인덱스로 인덱스를 정의 할 필요가 것입니다. EMPLOYEE_BASIC_TABLE보기로 액세스 할 수있는 '진짜'테이블이 호출되는 경우 예를 들어, EMPLOYEES 당신이

CREATE INDEX EMPLOYEES_UPPER_FIRST_NAME ON EMPLOYEES (UPPER(FIRST_NAME)); 

FIRST_NAME 열에 함수 기반 인덱스를 정의 할 수 있습니다 난 당신이 LIKE 비교가 정말 같이 필요 여부를 고려 제안 더 나은 성능을 얻기 위해 노력하는 것은 어려울 것입니다.

오라클 텍스트 인덱스를 조사하려는 경우 당신이 문서 here를 찾을 수 있습니다. 조각 인덱스를 문서화하거나 문서화하는 것이 더 적합하다고 생각하지만 아마도 아이디어를 줄 것입니다.

공유하고 즐길 수 있습니다. 하나는 어떤 이름 또는 이름의 일부를 볼 수있는 바와 같이

+2

쿼리가 인덱스를 사용할 수도 있다고 말하는 것이 더 정확할 것입니다 - 오라클은 빠른 전체 인덱스 스캔을 수행 할 수 있습니다. –

+0

답장을 보내 주셔서 감사합니다. 사실 저는 보편적 인 검색을 찾고 있습니다. 그렇기 때문에 LIKE가 유일한 옵션이고 인덱스에 관해서는 내 테이블에 각각의 열에 대해 인덱스 된 비트 맵이 있습니다. 어떤 사람이 좋은 대안을 제안 할 수 있다면 나는 정말로 열 받게 될 것입니다. –

+1

궁금합니다. 왜이 열에서 비트 맵 인덱스를 사용하기로 결정 했습니까? –

1

이 값이 미리 검색 할 함유 인덱스를 생성하는 방법이 없다. 그래서 그것이 당신을 여기에서 도와주지 않을 것입니다. 오라클은 전체 테이블 스캔을 수행하여 모든 단일 문자열에서 일치하는 항목을 확인합니다.

당신이 할 수있는 일은 그 스캔 속도를 높이는 것입니다.

당신은 (EMPLOYEE_BASIC_TABLE 4) */인스턴스/* + 평행 통해 병렬화하여 전체 테이블 스캔을 빠르게 할 수있다.

(이. 여기 내 조언이 될 것이다) 또는 당신이 아니라, 열 당 하나의 인덱스를 가진 모든 이름이 한 번만 스캔 될 수 있도록, 많은 반복적으로 사용되는 이름이 있다는 것을 알고에 의해 전체 테이블 스캔을 방지 할 수 있습니다. 그런 다음 Bob Jarvis가 제안하는 것처럼 기본 테이블에서 함수 기반 키를 사용합니다. 왜냐하면 어떤 이름 으로든 상위 함수를 사용하기 때문입니다. 가장 빠른 조합 색인은 다음과 같습니다.

create bitmap index idx_name_search on EMPLOYEE_BASIC_TABLE (upper(first_name || '|' || middle_name || '|' || last_name)) 

그래서 하나의 색인 만 조회 할 수 있습니다. (당신은 물론이 쿼리를 정확히 당신의 쿼리에서 사용해야 할 것입니다 : WHERE upper (first_name || '|'|| middle_name || '|'last_name) '% JOHN %'.)하지만 여전히, '% JOHN %'이 (가) 테이블 데이터의 2 %에만 영향을 미칠 수 있으므로 '% E %'이 (가) 80 %에 영향을 줄 수 있습니다. 최적화 프로그램은 결코 알 수 없습니다. 적어도 3 개의 문자가 포함 된 검색 문자열과 그렇지 않으면 사용할 색인 힌트가 포함 된 테이블 힌트를 사용하여 다른 선택 문을 추측 할 수 있습니다.

아시다시피, 생각해 보면 생각보다 복잡해집니다.병렬 힌트를 먼저 시도하는 것이 좋습니다. 어쩌면 이것은 이미 일을 충분히 가속화 할 수 있습니다.

+0

제출 한 코드를 방금 변경 했으므로 EA.EFFECTIVE_START_DATE 및 EA.EFFECTIVE_END_DATE가 결과 집합을 상당히 줄입니까? UPPER (H.RELATIONSHIP_CODE) = 'A'입니까? EMPLOYEE_HIS_DEPNDENT_TBL이 (가) 큰 테이블입니까? 그러면 함수 기반 인덱스가 UPPER (RELATIONSHIP_CODE)에 필요할 수 있습니다. 그리고 그것은 코드이므로 : UPPER 함수가 실제로 필요합니까? 필드가 실제로 'A'와 'a'둘 다 acceppt합니까? 그렇다면 그것을 바꿀 수도 있습니다. –

+0

EA.EFFECTIVE_END_DATE는 EMP_ASSIGNMENT_DTLS_MV에 여러 레코드가 있습니다. 왜냐하면 person_id가 여러 개 있습니다. EMPLOYEE_HIS_DEPNDENT_TBL에 4 개의 랙 데이터가 포함되어 있습니다. 아니요 'a'가 아니라 'A'만 허용됩니다. –

+0

이 질문을 할애 해 주셔서 고마워요. plz 조금 알려주세요. 어떻게하면 쿼리를 병렬 처리 할 수 ​​있습니까? –