2016-07-03 2 views
2

\d+ 명령에서 부분 색인을 볼 수있는 이유는 무엇입니까? Seq scan가 표시됩니다.일부 인덱싱이 적용되지 않습니다.

\d+ call_records; 

id     | integer      | not null default nextval('call_records_id_seq'::regclass) | plain |    | 

plain_crn   | bigint      | 
active    | boolean      | default true 
timestamp   | bigint      | default 0 


Indexes: 
    "index_call_records_on_plain_crn" UNIQUE, btree (plain_crn) 
    "index_call_records_on_active" btree (active) WHERE active = true 

예상대로 id에 대해 인덱스 스캔이있었습니다. 같은

EXPLAIN select * from call_records where id=1; 
             QUERY PLAN          
---------------------------------------------------------------------------------------- 
Index Scan using call_records_pkey on call_records (cost=0.14..8.16 rows=1 width=373) 
    Index Cond: (id = 1) 
(2 rows) 

active의 경우는 동일하지, plain_crn

EXPLAIN select * from call_records where plain_crn=1; 
               QUERY PLAN            
------------------------------------------------------------------------------------------------------ 
Index Scan using index_call_records_on_plain_crn on call_records (cost=0.14..8.16 rows=1 width=373) 
    Index Cond: (plain_crn = 1) 
(2 rows) 

간다하지만. 당신은 인덱스의 비용이

SET enable_seqscan = OFF; 

당신은 그것을 볼 스캔 테스트를 시작해야

EXPLAIN select * from call_records where active=true;                               QUERY PLAN       
----------------------------------------------------------------- 
Seq Scan on call_records (cost=0.00..12.00 rows=100 width=373) 
    Filter: active 
(2 rows) 
+1

'(분석, 상세)'설명 모든 쿼리에 대한 –

답변

3

PostgreSQL이 인덱스를 "활성"으로 사용하는지 여부는 true와 false의 비율에 따라 다릅니다. false보다 더 진실한 점에서 쿼리 플래너는 테이블 스캔이 더 빠를 것이라고 결정할 것입니다.

테스트 할 테이블을 만들고 무작위 (ish) 데이터를 백만 행로드했습니다. 참과 거짓

select active, count(*) 
from call_records 
group by active; 
 
active count 
-- 
f  499983 
t  500017 

행의 대략 같은 수 있습니다. 여기에 실행 계획이 있습니다.

explain analyze 
select * from call_records where active=true; 
 
"Bitmap Heap Scan on call_records (cost=5484.82..15344.49 rows=500567 width=21) (actual time=56.542..172.084 rows=500017 loops=1)" 
" Filter: active" 
" Heap Blocks: exact=7354" 
" -> Bitmap Index Scan on call_records_active_idx (cost=0.00..5359.67 rows=250567 width=0) (actual time=55.040..55.040 rows=500023 loops=1)" 
"  Index Cond: (active = true)" 
"Planning time: 0.105 ms" 
"Execution time: 204.209 ms" 

은 그 때 나는, "활성"업데이트 된 통계를 업데이트하고 다시 확인. 순차적 스캔을 끄면

update call_records 
set active = true 
where id < 750000; 

analyze call_records; 
explain analyze 
select * from call_records where active=true; 
 
"Seq Scan on call_records (cost=0.00..22868.00 rows=874100 width=21) (actual time=0.032..280.506 rows=874780 loops=1)" 
" Filter: active" 
" Rows Removed by Filter: 125220" 
"Planning time: 0.316 ms" 
"Execution time: 337.400 ms" 

내 경우에는, PostgreSQL의 올바른 결정을 내린 것을 보여줍니다. 테이블 스캔 (순차 스캔)은 약 10ms 더 빨랐습니다.

set enable_seqscan = off; 
explain analyze 
select * from call_records where active=true; 
 
"Index Scan using call_records_active_idx on call_records (cost=0.42..39071.14 rows=874100 width=21) (actual time=0.031..293.295 rows=874780 loops=1)" 
" Index Cond: (active = true)" 
"Planning time: 0.343 ms" 
"Execution time: 349.403 ms" 
+0

위대한 설명의 출력을 게시하시기 바랍니다. – Viren

+0

은 언급 된 곳입니다. – Viren

+1

@Viren : 쿼리 계획은 상당히 복잡합니다. 그러나 당신이 그것을 무너 뜨리면 그것은 모든 기본적인 논리입니다. 매뉴얼에서 * [ "Planner에서 사용하는 통계"] (https://www.postgresql.org/docs/current/static/planner-stats.html) * 부분부터 시작하십시오. 그리고 모든 세부 사항에 대해서는 * [ "플래너가 통계를 사용하는 방법"] (https://www.postgresql.org/docs/current/static/planner-stats-details.html) *을 참조하십시오. 그것은 여러 가지 요소에 따라 다르지만 일반적으로 테이블에서 ~ 5 % 이하 만 선택하면 인덱스 스캔이 비용을 지불합니다. 간단하고 어리석은 순차 스캔보다 오버 헤드가 상당히 많습니다. –

2

는 seqscan보다 훨씬 높은입니다. 테이블의 총 행 수는 매우 적을 수 있습니다. *을 선택하기 때문에 Postgres는 여전히 각 행을 조회해야하므로 색인을 확인한 다음 대부분의 페이지를 가져와야하는 것이 아니라 모든 행에 대해 순차적 검사를하는 것이 훨씬 쉽습니다.

관련 문제