2014-12-06 91 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 

我的任務是通過使用索引來優化查詢,但是我想不出一種使用索引來優化ag的方法gregate結果。

+0

沒有where子句,索引很少會有幫助。如果你想要一個有用的答案,你應該提及典型的用例(用另一個解釋分析)。否則,根據您的建議時間獲取所有發票的完整列表似乎是合理的。天真地說,我認爲'date_part('year':: text,「Invoice」,「InvoiceDate」)',BillingCountry或這兩者的某種組合的索引可能很有用,這取決於您想限制搜索結果通過。 – Ramfjord 2014-12-06 21:21:59

+2

您的查詢運行_less_而不是_one_ ** milli **秒。你需要多快?一納秒? – 2014-12-06 21:46:57

+0

考慮使用物化視圖,如果你不需要一個新的數據:http://www.postgresql.org/docs/9.3/static/rules-materializedviews.html視圖可以刷新每晚,它的結果將包括截至前一天的數據,但速度會非常快。 – krokodilko 2014-12-06 23:24:56

回答

1

正如Pavel,Ramfjord和馬所指出的那樣,使用索引對於如此少量的數據幾乎沒有用處。它太小了,Postgres讀取磁盤頁面或兩個頁面並處理內存中的所有內容會更快。

此外,您已經爲您的查詢制定了最佳的計劃。你要求Postgres在整個表上計算一個聚合並按照一定的順序返回它。 Postgres通過計算內存中的聚合而獲得收益,而不用麻煩先分類數據,通過使用散列分配中間結果;然後根據您的標準對少量結果進行排序。

2

你可以嘗試通過「SET enable_hashagg to OFF」懲罰Hashagg,但是對於小數據可能不會有任何益處。在這個用例中 - hashagg通常是用於聚合和排序的最快方法32kB非常快。

但是..你正在嘗試在412行的表上做性能基準測試。這是無稽之談。任何關於性能的想法對於與數據相關的2..3年的生產使用情況都有意義。