문제

"foo"와 "bar"라는 두 개의 필드가 있는 데이터베이스 테이블이 있다고 가정합니다.둘 다 고유하지는 않지만 각각 색인이 지정되어 있습니다.그러나 함께 색인화되는 대신 각각 별도의 색인을 갖습니다.

이제 다음과 같은 쿼리를 수행한다고 가정해 보겠습니다. SELECT * FROM sometable WHERE foo='hello' AND bar='world'; 내 테이블에는 foo가 'hello'인 엄청난 수의 행과 bar가 'world'인 소수의 행이 있습니다.

따라서 데이터베이스 서버가 내부적으로 수행하는 가장 효율적인 작업은 bar 인덱스를 사용하여 bar가 'world'인 모든 필드를 찾은 다음 foo가 'hello'인 행만 반환하는 것입니다.이것은 O(n) 여기서 n은 bar가 'world'인 행 수입니다.

그러나 fo 인덱스를 사용하고 결과를 검색하는 과정이 반대로 일어날 가능성이 있다고 생각합니다.이것은 O(m) 여기서 m은 foo가 'hello'인 행의 수입니다.

그렇다면 Oracle은 여기서 효율적으로 검색할 만큼 똑똑합니까?다른 데이터베이스는 어떻습니까?아니면 내 쿼리에서 올바른 순서로 검색하도록 알릴 수 있는 방법이 있나요?아마도 넣어서 bar='world' 처음으로 WHERE 절?

도움이 되었습니까?

해결책

Oracle은 거의 확실하게 가장 선택적 인덱스를 사용하여 쿼리를 구동하며 설명 계획으로 확인할 수 있습니다.

또한 Oracle은 두 인덱스 사용을 몇 가지 방법으로 결합 할 수 있습니다. BTree 인덱스를 비트 맵으로 변환하고 비트 맵 및 작업을 수행하거나 두 인덱스로 반환 된 Rowid에서 해시 조인을 수행 할 수 있습니다.

여기서 중요한 고려 사항 중 하나는 쿼리되는 값 사이의 상관 관계가있을 수 있습니다. foo = 'hello'가 테이블에서 값의 80%를 차지하고 Bar = 'world'가 10%를 차지하면 Oracle은 쿼리가 테이블 행의 0.8*0.1 = 8%를 반환 할 것으로 추정합니다. 그러나 이것은 정확하지 않을 수 있습니다. 쿼리는 값의 상관 관계에 따라 실제로 RWO의 10% 또는 행의 0%를 반환 할 수 있습니다. 이제 테이블 전체에 해당 행의 분포에 따라 인덱스를 사용하여 인덱스를 사용하는 것이 효율적이지 않을 수 있습니다. 필요한 행 ( "클러스터링 계수에 대한 Google)을 검색하려면 70% 또는 테이블 블록에 액세스해야 할 수도 있습니다.

11G에서는 내가 믿는이 상황에 도움을주기 위해 여러 가지 색상 통계를 수집 할 수 있습니다. 9i 및 10g에서 동적 샘플링을 사용하여 검색 할 행의 수를 매우 잘 추정 할 수 있습니다.

실행 계획을 얻으려면 다음을 수행하십시오.

explain plan for
SELECT *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

그것과 대조 :

explain plan for
SELECT /*+ dynamic_sampling(4) */
       *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

다른 팁

예, Oracle에 대한 쿼리와 함께 "힌트"를 줄 수 있습니다. 이 힌트는 데이터베이스에 주석 ( "/ * 힌트 */")으로 위장하고 주로 공급 업체별로 위장합니다. 따라서 하나의 데이터베이스에 대한 힌트는 다른 데이터베이스에서 작동하지 않습니다.

나는 여기에서 작은 테이블의 첫 번째 힌트 인 Index 힌트를 사용합니다. 보다 여기.

반면에,이 두 필드를 자주 검색한다면이 두 분야에서 인덱스를 만들지 않겠습니까? 나는 올바른 구문이 없지만

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo);

이런 식으로 데이터 검색은 매우 빠릅니다. 그리고 연결이 고유 한 경우, 당신은 단순히 빠르게 번개가되어야하는 독특한 색인을 만듭니다.

엘리,

당신이 쓴 댓글에서:

불행하게도 각각 자체 인덱스가 있는 많은 열이 있는 테이블이 있습니다.사용자는 모든 필드 조합을 쿼리할 수 있으므로 각 필드 조합에 대한 인덱스를 효율적으로 생성할 수 없습니다.그러나 인덱스가 필요한 필드가 두 개만 있다면 두 개의 인덱스를 사용하라는 귀하의 제안에 전적으로 동의합니다.– Eli Courtwright(9월 29일 15:51)

이것은 실제로 다소 중요한 정보입니다.때때로 프로그래머들은 질문을 할 때 자신보다 현명합니다.그들은 질문을 중요한 요점까지 추출하려고 노력하지만 지나치게 단순화하여 최상의 답을 얻는 것을 놓치는 경우가 많습니다.

이 시나리오는 정확히 알 수 없는 열 그룹이 where 절에서 사용되는 시간을 처리하기 위해 비트맵 인덱스가 발명된 이유입니다.

누군가 BMI가 낮은 카디널리티 열에만 해당되며 귀하의 사례에는 적용되지 않을 수 있다고 말하는 경우를 대비하여.낮음은 아마도 생각만큼 작지 않을 것입니다.유일한 실제 문제는 테이블에 대한 DML의 동시성입니다.이것이 작동하려면 단일 스레드 또는 희귀여야 합니다.

Oracle은 여기에서 효율적으로 검색 할만 큼 충분히 스마트합니까?

간단한 대답은 "아마도"입니다. 각 데이터베이스 공급 업체에는 쿼리 옵티마이저를 최적화하기 위해 노력하는 각 데이터베이스 공급 업체에 많은 사람들이 있으므로 생각조차하지 않은 일을하고있을 것입니다. 통계를 업데이트하면 아마도 더 많은 일이 될 것입니다.

먼저, 당신이 멋지고 정상적인 표준 B*-트리 색인에 대해 이야기하고 있다고 가정합니다. 비트 맵 인덱스에 대한 답은 근본적으로 다릅니다. 그리고 Oracle에는 답을 변경하거나 변경하지 않을 수도있는 다양한 유형의 인덱스에 대한 많은 옵션이 있습니다.

최소한, Optimizer가 특정 조건의 선택성을 결정할 수 있다면 더 선택적 인덱스 (즉, BAR의 인덱스)를 사용합니다. 그러나 데이터가 왜곡 된 경우 (열 표시 줄에 n 값이 있지만 특정 값의 선택성이 데이터의 1/n보다 크거나 작은 경우), 말을하려면 열에 히스토그램이 있어야합니다. 어떤 값이 더 많은 값이 될 가능성이 높습니다. 또한 Oracle 버전에 따라 BIND 변수를 사용하는 경우 (Oracle 버전에 따라) BIND 변수 엿보기에 문제가있을 수 있습니다.

잠재적으로, Oracle은 두 B*-tree 인덱스를 비트 맵으로 파리로 변환하고 비트 맵을 결합하여 두 인덱스를 사용하여 검색 해야하는 행을 찾을 수도 있습니다. 그러나 이것은 한 열이 매우 선택적인 두 개의 열만있는 경우 다소 특이한 쿼리 계획입니다.

Oracle에 쿼리 계획을 표시 할 수도 있으므로 먼저 어떤 색인이 사용되는지 정확히 알 수 있습니다.

사용할 색인에 대한 힌트를 제공 할 수 있습니다. 나는 Oracle에 익숙하지 않지만 MySQL에서는 사용을 사용할 수 있습니다 | INGORE | FORCE_INDEX (참조 여기 자세한 사항은). 최상의 성능을 위해서는 결합 된 인덱스를 사용해야합니다.

가장 좋은 방법은 Bar의 색인에 foo를 추가하거나 Foo의 지수 (또는 둘 다)에 막대를 추가하는 것입니다. FOO의 인덱스가 막대의 색인이 포함되어 있다면, 추가 색인 수준은 해당 지수의 현재 사용에서 FOO 지수의 유틸리티에 영향을 미치지 않으며 해당 지수 유지의 성능에 큰 영향을 미치지 않지만 데이터베이스에 추가로 제공됩니다. 예제와 같은 쿼리 최적화에서 작업 할 정보.

그것보다 낫다.

인덱스는 항상 전체 테이블 스캔보다 빠릅니다. 따라서 무대 뒤에서 Oracle (및 해당 문제에 대한 SQL 서버)은 먼저 두 지수의 행 범위를 찾습니다. 그런 다음 어떤 범위가 더 짧은 지 (내부 조인임을 보는) 더 짧은 범위를 살펴보고, 더 짧은 범위를 반복하여 두 개 중 더 큰 일치를 찾을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top