A 부분 배트맨 토토은 테이블의 하위 집합에 대해 구축된 인덱스입니다. 하위 집합은 조건식(라고 함)으로 정의됩니다.술어부분 배트맨 토토의). 인덱스에는 조건자를 만족하는 테이블 행에 대한 항목만 포함됩니다. 부분 배트맨 토토은 특수한 기능이지만 유용한 여러 상황이 있습니다.
부분 배트맨 토토을 사용하는 주요 이유 중 하나는 공통 값의 색인 생성을 피하기 위한 것입니다. 공통 값(모든 테이블 행의 몇 퍼센트 이상을 차지하는 값)을 검색하는 쿼리는 어쨌든 인덱스를 사용하지 않으므로 해당 행을 인덱스에 보관할 필요가 전혀 없습니다. 이렇게 하면 인덱스 크기가 줄어들어 인덱스를 사용하는 쿼리 속도가 빨라집니다. 또한 모든 경우에 인덱스를 업데이트할 필요가 없기 때문에 많은 테이블 업데이트 작업 속도가 빨라집니다.예 11.1이 아이디어의 가능한 적용을 보여줍니다.
예제 11.1. 공통 값을 제외하도록 부분 인덱스 설정
웹 서버 액세스 로그를 데이터베이스에 저장한다고 가정해 보세요. 대부분의 액세스는 조직의 IP 주소 범위에서 발생하지만 일부는 다른 곳(예: 전화 접속 연결을 사용하는 직원)에서 발생합니다. IP별 검색이 주로 외부 액세스를 위한 것이라면 조직의 서브넷에 해당하는 IP 범위를 배트맨 토토화할 필요가 없을 것입니다.
다음과 같은 테이블을 가정해보세요:
CREATE TABLE access_log(
URL varchar,
client_ip inet,
...
);
우리의 예에 적합한 부분 배트맨 토토을 생성하려면 다음과 같은 명령을 사용하십시오:
INDEX 생성 access_log_client_ip_ix ON access_log (client_ip)
어디에 있지 않습니까(client_ip inet '192.168.100.0' AND
클라이언트_ip < inet '192.168.100.255');
이 색인을 사용할 수 있는 일반적인 쿼리는 다음과 같습니다:
선택 * access_log에서 WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';
이 색인을 사용할 수 없는 쿼리는 다음과 같습니다:
선택 * access_log에서 WHERE client_ip = inet '192.168.100.23';
이런 종류의 부분 인덱스를 사용하려면 공통 값이 미리 결정되어야 하므로 이러한 부분 인덱스는 변경되지 않는 데이터 분포에 가장 잘 사용됩니다. 새로운 데이터 배포에 맞게 배트맨 토토을 가끔 다시 생성할 수 있지만 이로 인해 유지 관리 노력이 추가됩니다.
부분 인덱스의 또 다른 가능한 용도는 일반적인 쿼리 작업 부하에 관심이 없는 값을 인덱스에서 제외하는 것입니다. 이것은에 표시됩니다.예 11.2. 이는 위에 나열된 것과 동일한 이점을 가져오지만 다음을 방지합니다.“흥미롭지 않음”해당 인덱스를 통해 값에 액세스할 수 없습니다. 이 경우 인덱스 스캔이 수익성이 있을지라도 마찬가지입니다. 분명히 이런 종류의 시나리오에 대해 부분 인덱스를 설정하려면 많은 주의와 실험이 필요합니다.
예제 11.2. 흥미롭지 않은 값을 제외하기 위해 부분 인덱스 설정
청구된 주문과 청구되지 않은 주문이 모두 포함된 테이블이 있고 청구되지 않은 주문이 전체 테이블의 작은 부분을 차지하지만 가장 많이 액세스된 행인 경우 청구되지 않은 행에만 인덱스를 생성하여 성능을 향상시킬 수 있습니다. 인덱스를 생성하는 명령은 다음과 같습니다.
CREATE INDEX 주문_unbilled_index ON 주문(order_nr)
청구된 곳이 사실이 아닙니다.
이 색인을 사용하기 위한 가능한 쿼리는 다음과 같습니다:
SELECT * FROM 주문이 청구된 곳이 사실이 아니며 AND order_nr < 10000;
그러나 배트맨 토토은 관련되지 않은 쿼리에도 사용될 수 있습니다.order_nr전혀, 예:
SELECT * 청구된 주문이 사실이 아니며 금액이 5000.00보다 큽니다.
이것은 부분 배트맨 토토만큼 효율적이지 않습니다.금액열은 시스템이 전체 색인을 스캔해야 하기 때문에 가능합니다. 그러나 미청구 주문이 비교적 적은 경우 이 부분 배트맨 토토을 사용하여 미청구 주문을 찾는 것이 유리할 수 있습니다.
이 쿼리는 이 배트맨 토토을 사용할 수 없습니다.
SELECT * FROM 주문 WHERE order_nr = 3501;
주문 3501은 청구되거나 청구되지 않은 주문에 속할 수 있습니다.
예 11.2또한 인덱싱된 열과 조건자에 사용된 열이 일치할 필요가 없음을 보여줍니다.PostgreSQL인덱싱되는 테이블의 열만 포함되는 한 임의의 조건자가 있는 부분 인덱스를 지원합니다. 그러나 조건자는 인덱스의 이점을 얻을 것으로 예상되는 쿼리에 사용된 조건과 일치해야 한다는 점을 명심하십시오. 정확하게 말하면 시스템이 다음을 인식할 수 있는 경우에만 부분 인덱스를 쿼리에 사용할 수 있습니다.어디쿼리의 조건은 수학적으로 인덱스의 조건자를 의미합니다.PostgreSQL다른 형식으로 작성된 수학적으로 동등한 표현식을 인식할 수 있는 정교한 정리 증명자가 없습니다. (이러한 일반 정리 증명은 만들기가 매우 어려울 뿐만 아니라 실제 사용하기에는 너무 느릴 수도 있습니다.) 시스템은 예를 들어 단순한 불평등 의미를 인식할 수 있습니다.“x < 1”암시“x < 2”; 그렇지 않으면 조건자 조건이 쿼리의 일부와 정확히 일치해야 합니다.어디에서조건이 아니면 인덱스가 사용 가능한 것으로 인식되지 않습니다. 일치는 런타임이 아닌 쿼리 계획 시간에 발생합니다. 결과적으로 매개변수화된 쿼리 절은 부분 인덱스에서 작동하지 않습니다. 예를 들어 매개변수가 있는 준비된 쿼리는 다음과 같이 지정할 수 있습니다.“x < ?”절대 암시하지 않음“x < 2”매개변수의 가능한 모든 값에 대해.
부분 인덱스의 세 번째 가능한 용도는 쿼리에서 인덱스를 전혀 사용할 필요가 없다는 것입니다. 여기서의 아이디어는 다음과 같이 테이블의 하위 집합에 대해 고유한 인덱스를 생성하는 것입니다.예 11.3. 이는 인덱스 조건자를 충족하지 않는 행을 제한하지 않고 인덱스 조건자를 충족하는 행 간에 고유성을 적용합니다.
예제 11.3. 부분 고유 인덱스 설정
테스트 결과를 설명하는 테이블이 있다고 가정합니다. 우리는 하나만 존재하도록 하고 싶습니다.“성공”주어진 주제 및 대상 조합에 대한 항목이지만 개수에는 제한이 없을 수 있습니다.“실패”항목. 이를 수행하는 한 가지 방법은 다음과 같습니다.
CREATE TABLE 테스트(
주제 텍스트,
대상 텍스트,
성공 부울,
...
);
CREATE UNIQUE INDEX 테스트_success_constraint ON 테스트(주제, 대상)
어디에서 성공;
이것은 성공한 테스트가 적고 실패한 테스트가 많을 때 특히 효율적인 접근 방식입니다. 또한를 사용하여 고유한 부분 인덱스를 생성하여 열에 하나의 Null만 허용할 수도 있습니다.NULL입니다제한.
마지막으로 부분 배트맨 토토을 사용하여 시스템의 쿼리 계획 선택을 무시할 수도 있습니다. 또한 특이한 분포를 가진 데이터 세트로 인해 시스템이 실제로는 사용하지 말아야 할 인덱스를 사용하게 될 수도 있습니다. 이 경우 잘못된 쿼리에 사용할 수 없도록 인덱스를 설정할 수 있습니다. 일반적으로,포스트그레SQL인덱스 사용에 대해 합리적인 선택을 합니다(예: 공통 값을 검색할 때 이를 방지하므로 이전 예에서는 실제로 인덱스 크기만 절약하고 인덱스 사용을 피할 필요는 없음). 완전히 잘못된 계획 선택은 버그 보고서의 원인입니다.
부분 인덱스를 설정한다는 것은 적어도 쿼리 플래너가 알고 있는 만큼만 알고 있다는 것을 의미하며, 특히 인덱스가 언제 수익성이 있을지 알 수 있다는 것을 명심하십시오. 이러한 지식을 형성하려면 배트맨 토토이 어떻게 생성되는지에 대한 경험과 이해가 필요합니다.PostgreSQL일. 대부분의 경우 일반 인덱스에 비해 부분 인덱스의 이점은 최소화됩니다. 다음과 같이 매우 비생산적인 경우가 있습니다.예 11.4.
예제 11.4. 분할 대신 부분 인덱스를 사용하지 마십시오.
예를 들어, 겹치지 않는 부분 배트맨 토토의 대규모 세트를 생성하려는 유혹을 받을 수 있습니다.
CREATE INDEX mytable_cat_1 ON mytable (데이터) WHERE 카테고리 = 1; mytable(데이터) WHERE 카테고리 = 2에서 INDEX mytable_cat_2를 생성합니다. mytable(데이터) WHERE 카테고리 = 3에서 INDEX mytable_cat_3을 생성합니다. ... 인덱스 mytable_cat_ 생성NON mytable (데이터) WHERE 카테고리 =N;
이것은 나쁜 생각입니다! 거의 확실하게 다음과 같이 선언된 단일 비부분 인덱스를 사용하는 것이 더 나을 것입니다.
mytable(카테고리, 데이터)에 INDEX mytable_cat_data 생성;
(아래에 설명된 이유로 카테고리 열을 먼저 입력하세요.PostgreSQL : 문서 : 10 : 11.3. 멀티 컬럼 젠 토토.) 이 큰 인덱스의 검색은 작은 인덱스의 검색보다 몇 가지 더 많은 트리 수준을 거쳐야 할 수도 있지만 부분 인덱스 중 적절한 항목을 선택하는 데 필요한 플래너 노력보다 비용이 적게 듭니다. 문제의 핵심은 시스템이 부분 인덱스 간의 관계를 이해하지 못하고, 현재 쿼리에 적용 가능한지 확인하기 위해 각각을 힘들게 테스트한다는 것입니다.
테이블이 충분히 커서 단일 인덱스가 실제로 좋지 않은 경우에는 대신 파티셔닝을 사용하는 것을 고려해야 합니다(참조스포츠 토토 베트맨 PostgreSQL : 문서 : 10 : 5.10. 테이블 파티셔닝). 이 메커니즘을 통해 시스템은 테이블과 인덱스가 겹치지 않는다는 것을 이해하므로 더 나은 성능이 가능합니다.
부분 배트맨 토토에 대한 자세한 내용은 다음에서 찾을 수 있습니다.[ston89b], [olson93]및[seshadri95].