2016-07-05 3 views
1

У меня есть эта таблица:Почему Postgres не использует индекс с Distinct?

CREATE TABLE public.prodhistory (
    curve_id   int4 NOT NULL, 
    start_prod_date date NOT NULL, 
    prod_date   date NOT NULL, 
    monthly_prod_rate float4 NOT NULL, 
    eff_date   timestamp NOT NULL, 
    /* Keys */ 
    CONSTRAINT prodhistorypk 
    PRIMARY KEY (curve_id, prod_date, start_prod_date, eff_date), 
    /* Foreign keys */ 
    CONSTRAINT prodhistory2typecurves_fk 
    FOREIGN KEY (curve_id) 
    REFERENCES public.typecurves(curve_id) 
) WITH (
    OIDS = FALSE 
); 

CREATE INDEX prodhistory_idx_curve_id01 
    ON public.prodhistory 
    (curve_id); 

с ~ 42M строк.

И я выполнить этот запрос:

SELECT DISTINCT curve_id FROM prodhistory 

который я ожидал бы очень быстро, учитывая индекс. Но нет, 270 секунд. Так я объясняю, и я получаю:

HashAggregate (cost=824870.03..824873.08 rows=305 width=4) (actual time=211834.018..211834.097 rows=315 loops=1) 
    Output: curve_id 
    Group Key: prodhistory.curve_id 
    -> Seq Scan on public.prodhistory (cost=0.00..718003.22 rows=42746722 width=4) (actual time=12.751..200826.299 rows=43218808 loops=1) 
     Output: curve_id  
Planning time: 0.115 ms 
Execution time: 211848.137 ms 

Я не испытывал при чтении этих планов, а Seq сканирование на БД кажется плохим.

Любые мысли? Я как бы в шоке.

+0

Я имею в виду, сколько различных значений существует для 'curve_id' ?. Кроме того, какой смысл делать ПК всей таблицей? – Lamak

+0

Покажите нам вывод 'explain (analysis, verbose)'. –

+0

@lamak - в настоящее время существует 300 различных значений и, вероятно, закончится с точностью до 1000. Кроме того, PK - это то, что я могу обновлять каждую строку - данные обновляются ежемесячно, но только последние данные (последние два года «prod_date») обновляется. И ПК определяет, что уникально в таблице, за хорошую практику. – Marc

ответ

2

Этот план выбран потому, что PostgreSQL считает его дешевле.

Вы можете сравнить, установив

SET enable_seqscan=off; 

, а затем повторно запустив свой EXPLAIN (ANALYZE) заявление. Сравните cost и actual time в обоих случаях и проверьте, правильно ли оценивается PostgreSQL или нет.

Если вы обнаружите, что использование Index Scan или Index Only Scan на самом деле дешевле, вы можете рассмотреть возможность свернуть параметры затрат, чтобы они соответствовали вашей машине, например. ниже random_page_cost или cpu_index_tuple_cost или поднять cpu_tuple_cost.

+0

Использование 'SET enable_seqscan = off;' ИСПОЛЬЗУЕТ изменить план запроса на «Индекс только сканировать», но все же нет никакой выгоды от наличия множества повторяющихся значений. Число отсканированных строк по-прежнему намного выше числа возвращаемых строк. Я ожидал бы, что postgres будут достаточно умны, чтобы перейти к следующему отличительному значению, вместо того, чтобы сканировать их все. –

+0

PostgreSQL не может этого сделать. Даже если бы это было возможно, это было бы полезно только в том случае, если существует несколько различных значений, поскольку последовательное сканирование обычно происходит быстрее, чем случайный доступ. –