2013-03-20 4 views
1

이 쿼리는 매우 느리게 실행됩니다. 왜? 기타는 괜찮습니다. 색인은 좋다고 생각합니다.Postgresql 매우 느린 쿼리

explain analyze 
select "e_inst"."si_id" as "c0" 
from "e_inst" as "e_inst" 
group by "e_inst"."si_id" 
order by "e_inst"."si_id" ASC NULLS LAST 

쿼리 계획 :

Sort (cost=12221.87..12221.90 rows=68 width=4) (actual time=1115.377..1115.433 rows=81 loops=1) 
    Sort Key: si_id 
    Sort Method: quicksort Memory: 28kB 
    -> HashAggregate (cost=12221.25..12221.45 rows=68 width=4) (actual time=1115.198..1115.261 rows=81 loops=1) 
     -> Seq Scan on e_inst (cost=0.00..11920.07 rows=602357 width=4) (actual time=0.021..611.570 rows=602357 loops=1) 
Total runtime: 1115.538 ms 

테이블과 인덱스를 만듭니다

CREATE TABLE e_inst (
    id integer NOT NULL, 
    ip numeric, 
    gu character varying, 
    referrer character varying, 
    proc integer, 
    loke_id integer, 
    top_id integer, 
    si_id integer, 
    kop integer, 
    count integer, 
    created integer, 
    modified integer, 
    timepop integer, 
    count_active character varying, 
    country character(3), 
    info character varying 
); 

CREATE INDEX "topEnhance" ON e_inst USING btree (created, top_id); 
CREATE INDEX "procEnhance" ON e_inst USING btree (created, proc); 
CREATE INDEX "countryEnhance" ON e_install USING btree (created, country); 
CREATE INDEX "createdE" ON e_inst USING btree (created); 
ALTER TABLE e_inst CLUSTER ON "createdE"; 
CREATE INDEX "lokeE" ON e_inst USING btree (loke_id); 
CREATE INDEX "lokeEnhance" ON e_inst USING btree (created, loke_id); 
CREATE INDEX "siE" ON e_inst USING btree (si_id); 
CREATE INDEX "siEnhance" ON e_inst USING btree (created, si_id); 
CREATE INDEX "kopEnhance" ON e_inst USING btree (created, kop); 
+0

참고 : 색인 된 데이터의 카디널리티가 높지 않으면 색인이 도움이되지 않습니다. – bernie

+0

PGSQL 멍청한 것에 대해 죄송합니다. 높은 카디널리티는 무엇입니까? –

+1

군중이 내가 할 수있는 것보다 더 잘 설명 할 수 있기 때문에 : http://en.wikipedia.org/wiki/Cardinality_(SQL_statements) – bernie

답변

0

PostgreSQL 9.2로 업그레이드되었습니다. 이제 색인 만 스캔합니다! a_horse_with_no_name 님, 업그레이드하라고 조언 해 주신 분께 감사드립니다.

3

인덱스는 전체 테이블을 처리하는 쿼리를 사용하지 않을 수 있습니다.

사실 600k 레코드를 검색 중입니다. 실제로 이것이 1 초 넘게 걸린다는 것은 실제로 인상적입니다.

이제이 경우, 600k 레코드에서 81 개의 다른 값을 추출하려고합니다. 당신이 원할 수있는 것은 재귀 쿼리를 구성하여 한 행을 81 번 페치 (fetch)하는 것입니다. 이 일 수 있지만 더 빠른 것은 아닙니다. 일반적으로 나는 이보다 훨씬 적은 수의 행이 반환되는 곳에서 이것을 사용합니다. 그러나 여기에 예제가 있습니다 :

WITH RECURSIVE sparse_scan AS (
    SELECT min(si_id) as si_id FROM e_inst 
    UNION ALL 
    SELECT min(si_id) as si_id 
     FROM e_inst 
     JOIN (select max(si_id) as last FROM sparse_scan) s 
    WHERE s.last < si_id 
) 
SELECT si_id as c0 FROM sparse_scan; 

이것은 순차 스캔을 81 인덱스 스캔으로 바꿉니다.

+0

몬드리안이 내 쿼리를 작성하기 때문에 쿼리를 변경할 수 없습니다. –