8

나는 int이고 btree 인덱스를 가진 컬럼 c가있는 테이블 t를가집니다.PostgreSQL :이 간단한 쿼리가 인덱스를 사용하지 않는 이유는 무엇입니까?

다음 쿼리가이 인덱스를 사용하지 않는 이유는 무엇입니까? 인덱스의

HashAggregate (cost=1005817.55..1005817.71 rows=16 width=4) 
    -> Seq Scan on t (cost=0.00..946059.84 rows=23903084 width=4) 

나의 이해는 제한되어 있지만 이러한 쿼리는 인덱스의 목적이라고 생각 :

explain select c from t group by c; 

내가 얻을 결과입니다.

답변

4

쿼리에 확실히 인덱스를 사용할 수 있습니다. 특정 경우에 그렇지 않은 이유는 데이터의 특정 크기와 분포에 따라 달라집니다. 조사하려면 SET enable_seqscan TO off을 사용할 수 있습니다.

+2

인덱스를 사용하지 않을 경우 어떤 상황에서 돈을 지불하지 않습니까? 이 예제에서 크기에 대해 이야기 할 때 적어도 어떤 배포판도 상상할 수 없습니다. – David

+0

@ David : 전체 인덱스 스캔은 테이블의 순차 스캔보다 훨씬 비쌉니다. 인덱스는 일반적으로 테이블의 작은 하위 집합을 선택하는 경우에만 유용합니다. –

+1

이것은 잘못되었습니다. SELECT DISTINCT x FROM t;와 같은 질의는'(x)'에 대한 인덱스를 사용할 수 있어야합니다. 전체 색인을 읽는 것이 전체 표를 읽는 것보다 저렴해야합니다. 그러나 Postgres는 내가 아는 한 [Loose Index scan] (https://wiki.postgresql.org/wiki/Loose_indexscan)을 구현하지 않았습니다. –

3

전체 테이블을 스캔해야하므로 인덱스를 통해 검색하는 것이 아무런 이점이 없습니다. ("Covering indices"는 MVCC 구현으로 인해 PostgreSQL의 성능 기술로 유용하지 않습니다.)

+0

PostgreSQL 9.2는 색인 전용 검사와 함께 제공됩니다 : http://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.2#Index-only_scans – qerub

5

이 쿼리는 루스 인덱스 스캔이라는 최적화를 사용하여 수행 할 수 있습니다. 그러나 PostgreSQL은 아직이 최적화를 구현하지 않으므로 대신 테이블 스캔을 사용합니다.

주요 데이터베이스 중, 내가 아는 한 MySQL has implemented loose index scan (아마도 오라클도 될까요?). PostgreSQL hasn't이이 기능을 구현했습니다.

+0

PostgreSQL의 아키텍처는 현재 사용중인 경우에도 테이블을 방문해야한다는 것을 의미합니다 색인 당신이 모든 행을 어쨌든 때려야 할 때 그것은 훨씬 더 비쌉니다. 나는 mysql에서 엔진이 제대로 작동하기 위해 커버 닝 인덱스를 포함해야한다고 가정하지만, mysql을 잘 모른다. –

+3

@Scott Marlowe :하지만 요점은 느슨한 인덱스 스캔을 사용하면 모든 행을 공격하지 않아도된다는 것입니다. 이런 이유로 MySQL은 PostgreSQL보다 수백 또는 수천 배 빠른 쿼리 유형 ('c'의 별개 값이 거의없는 매우 큰 테이블에서) 일 수 있습니다. 스키마 디자인의 간단한 변경 (새 테이블 도입)이 문제를 해결하기 때문에 우선 순위가 낮은 기능 요청입니다. –

+1

인덱스 스캔 *이라고도하며 Oracle, SQL Server 및 DB2에서도이를 구현합니다. 하지만 수천 배 빠른 쿼리 *를 만드는 것은 의심 스럽습니다. 빨리, 네. 하지만 그 정도는 아닙니다. (하지만 저는 Postgres가 가지고 있지 않다는 것에 정말 수치 스럽습니다.) –

관련 문제