2010-07-01 4 views
2

2 개의 외래 키가있는 테이블이 있는데, fk1과 fk2를 호출 할 수 있습니다. 둘 다 동일한 유형과 동일한 색인을 가지고 있습니다. 그러나 간단한 선택 쿼리를 "설명"하면 쿼리 계획이 완전히 달라집니다. fk2PostgreSql : 동일한 열을 가진 다른 쿼리 계획

를 들어

Index Scan using fk1_idx on mytable (cost=0.00..9.32 rows=2 width=4) 
    Index Cond: (fk1 = 1) 

explain select * from mytable where fk2 = 1; 

결과

explain select * from mytable where fk1 = 1; 

결과 : FK1를 들어

Bitmap Heap Scan on mytable (cost=5.88..659.18 rows=208 width=4) 
    Recheck Cond: (fk2 = 1) 
    -> Bitmap Index Scan on fk2_idx (cost=0.00..5.83 rows=208 width=0) 
     Index Cond: (fk2 = 1) 

두 번째는 더 비효율적 인 것 같다. 잠재적으로 더 많은 결과를 반환한다는 사실 때문에 더 복잡한 쿼리가 효과가 있습니까?

답변

5

예, 이것은 술어의 "선택성"("where ..."절)으로 불립니다.

술어가 테이블의 행의 작은 부분을 선택하는 경우, 그것은 단지 몇 페이지를 가져올 것 때문에, 테이블 데이터에 임의적으로 정렬 된 액세스를 개별적으로 하나 하나를 가져 의미가 있습니다.

선택할 행 수가 많아지면 비트 맵 검사가 더 적절 해집니다. 색인은 테이블 내의 어떤 페이지가 "흥미로운"것인지를 결정하는 데 사용되며, 그 페이지는 배치 된 순서대로 스캔됩니다 테이블 데이터 파일 이것은 파일 시스템/디스크 시스템에 의해 훨씬 효율적으로 제공 될 가능성이있는 인접한 페이지를 함께 요청할 수 있다는 장점이 있습니다. (물론 이것은 테이블 데이터 파일이 합리적으로 조각 모음되지 않은 것에 달려 있습니다.) 각 페이지 내의 실제 흥미로운 튜플 집합은 유지되지 않으므로 검색된 페이지에서 각 튜플에 대한 술어를 다시 평가해야합니다. 따라서 쿼리의 "다시 확인 cond". (이 전략의 한 가지 장점은 여러 인덱스 룩업에서 "흥미로운 페이지"비트 맵을 단순히 AND 연산 (ORing)하여 복수의 독립적 인 인덱스의 룩업을 결합 할 수 있다는 것입니다.

선택할 행 수 테이블의 대부분이 "흥미로운"것으로 표시 될 가능성이있는 결과가 나타나는 것처럼 색인을 검색하는 이점이 줄어 듭니다. 따라서 결국 순차적 스캔이 적절하게됩니다. 모든 페이지는 순서대로 진행되며 색인은 무시됩니다.

IIRC는 인덱스 스캔, 15-50 % 비트 맵 스캔, 50 % + seq 스캔과 같이 테이블의 15 % 미만을 요청하면 문제가 발생하는 경향이 있습니다. 아주 대략. 이것은 random_page_cost와 seq_page_cost의 상대적인 설정에 의해 많은 영향을받습니다 (예 : effective_cache_size).

PostgreSQL은 일반적인 값과 빈도 및 데이터베이스의 각 열에 대한 다른 값의 막대 그래프에 대한 통계를 수집합니다. 이것은 선택성을 추정하는 데 사용되며 EXPLAIN 출력에서 ​​본 "행"추정치를 채 웁니다. 설명서에는 이것이 어떻게 수행되는지에 대한 설명이 포함되어 있습니다. http://www.postgresql.org/docs/current/static/planner-stats-details.html

2

예, 쿼리 계획은 테이블의 내용에 대한 통계 데이터를 기반으로합니다. "vacuum analyze;"를 실행하십시오. 지금은 통계 데이터를 데이터로 유지해야합니다.