2014-12-06 3 views
0

У меня есть следующий запрос/Вид:Postgres оптимизации индекса запросов на основе агрегатов

CREATE OR REPLACE VIEW "SumAndSalesPerCountryYear" AS 
SELECT date_part('year'::text, "Invoice"."InvoiceDate") AS year, 
    "Invoice"."BillingCountry" AS country, 
    sum("Invoice"."Total") AS total 
    FROM "Invoice" 
    GROUP BY date_part('year'::text, "Invoice"."InvoiceDate"), "Invoice"."BillingCountry" 
    ORDER BY date_part('year'::text, "Invoice"."InvoiceDate") DESC, sum("Invoice"."Total") DESC; 

Моя структура таблицы выглядит следующим образом:

CREATE TABLE "Invoice" 
(
    "InvoiceId" integer NOT NULL, 
    "CustomerId" integer NOT NULL, 
    "InvoiceDate" timestamp without time zone NOT NULL, 
    "BillingAddress" character varying(70), 
    "BillingCity" character varying(40), 
    "BillingState" character varying(40), 
    "BillingCountry" character varying(40), 
    "BillingPostalCode" character varying(10), 
    "Total" numeric(10,2) NOT NULL, 
    CONSTRAINT "PK_Invoice" PRIMARY KEY ("InvoiceId"), 
    CONSTRAINT "FK_InvoiceCustomerId" FOREIGN KEY ("CustomerId") 
     REFERENCES "Customer" ("CustomerId") MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION 
) 
WITH (
    OIDS=FALSE 
); 

Текущий план выполнения

Sort (cost=33.65..34.54 rows=354 width=21) (actual time=0.691..0.698 rows=101 loops=1)" 
    Sort Key: (date_part('year'::text, "Invoice"."InvoiceDate")), (sum("Invoice"."Total")) 
    Sort Method: quicksort Memory: 32kB 
    -> HashAggregate (cost=14.24..18.67 rows=354 width=21) (actual time=0.540..0.567 rows=101 loops=1) 
     -> Seq Scan on "Invoice" (cost=0.00..11.15 rows=412 width=21) (actual time=0.015..0.216 rows=412 loops=1) 
Total runtime: 0.753 ms 

Моя задача - оптимизировать запрос с использованием индексов, однако я не могу придумать способ использования индексов для оптимизации результатов агрегации.

+0

Индексы редко будут полезны без предложения where. Вы должны указать типичный вариант использования (с другим объяснением), если вы хотите получить полезный ответ. В противном случае получение полного списка всех счетов-фактур за время, которое вы предложили, кажется разумным. Наивно, я бы подумал, что индекс в 'date_part ('year' :: text,« Invoice ».« InvoiceDate »)', BillingCountry или какая-то комбинация из них может быть полезна в зависимости от того, для чего вы хотите ограничить результаты поиска от. – Ramfjord

+2

Ваш запрос выполняется для _less_ than _one_ ** milli ** second. Как быстро вам это нужно? Одна наносекунда? –

+0

Рассмотрите возможность использования материализованного представления, если вам не нужны свежие данные: http://www.postgresql.org/docs/9.3/static/rules-materializedviews.html. Просмотр может обновляться каждую ночь, и результаты будут включают данные только до предыдущего дня, но будут очень быстрыми. – krokodilko

ответ

1

Как отметил Павел, Рамфьорд и лошадь с использованием индекса мало используют с таким крошечным количеством данных. Он настолько мал, что Postgres быстрее читает страницу диска или два и обрабатывает все в памяти.

Кроме того, у вас есть самый лучший план по вашему запросу. Вы просите Postgres вычислить совокупность по всей таблице и вернуть ее в определенном порядке. Postgres продолжает вычислять совокупность в памяти, не пытаясь сначала сортировать данные, назначая промежуточные результаты с использованием хэша; он сортирует небольшое количество результатов в соответствии с вашими критериями.

2

Вы можете попытаться оштрафовать Hashagg на «SET enable_hashagg to OFF», но, вероятно, для небольших данных не будет никакой пользы от индекса .. в этом случае использования - hashagg обычно самый быстрый метод для агрегации и сортировки 32kB довольно быстро.

Но .. вы пытаетесь выполнить тест производительности на столе с 412 строками. Это вздор. Любое мышление о производительности имеет смысл в данных с размером, относящимся к 2,33 года использования продукции.

Смежные вопросы