2013-03-20 296 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 2013-03-20 22:23:02

+0

對不起,作爲PGSQL noob,什麼是高基數? – 2013-03-20 22:27:01

+1

因爲人羣可以比我更好地解釋:http://en.wikipedia.org/wiki/Cardinality_(SQL_statements) – bernie 2013-03-20 22:27:53

回答

0

升級到PostgreSQL 9.2。現在這只是一個索引只掃描! 工程很好,感謝a_horse_with_no_name誰建議我升級。

3

指標都不會通過處理整個表的查詢使用。

事實是,您正在檢索和處理 600k條記錄。它在一秒鐘之內完成,實際上令人印象深刻。

現在在這種情況下,您正試圖從600k條記錄中提取81個不同的值。你可能想要做的是構造一個遞歸查詢,使其獲取81行一行。這可能會更快,但沒有保證。通常我使用返回的行數少得多的地方。然而,這裏是一個例子:

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

我想這樣做,但我無法更改查詢,因爲Mondrian構建了我的查詢。 – 2013-03-21 13:17:13