2012-02-14 54 views
1

我不是分貝speccialist,所以問題=)如何優化sql查詢?看起來很明顯很慢?

如何優化這樣的:

select count(DISTINCT userid) 
from users 
where date_trunc('month',login_date)=date_trunc('month','2012-01-12'::date) 

錶行數是小於150萬。我在login_date上有一個索引,雖然查詢執行時間與沒有它相同。此外,字段用戶ID是主鍵。

在服務器機器上,這個查詢需要超過2000毫秒。第一個能夠幫助發揮出最佳表現的人會獲得聲譽++:D

---------------- a'b'c'd'e'f'g' h'SOLUTION ----------------------------------

CREATE OR REPLACE FUNCTION my_date_trunc_month(some_date DATE) 
    RETURNS DATE 
AS $$ 
BEGIN 
    return date_trunc('month',$1); 
END; 
$$LANGUAGE plpgsql 
IMMUTABLE; 


CREATE INDEX computedIdx ON gameuser_daily_activity (my_date_trunc_month(login_date)); 

select count(DISTINCT gameuser_fk) from gameuser_daily_activity where my_date_trunc_month(login_date)=my_date_trunc_month('2012-01-12'::date) 

AND it takes 110ms: )

回答

4

定義這個指數:

CREATE INDEX computedIdx ON users (date_trunc('month',login_date))

+0

Hm,ERROR:索引表達式中的函數必須標記爲IMMUTABLE – whatswrong 2012-02-14 13:53:50

+0

http://stackoverflow.com/questions/5973030/error-functions-in-index-expression-must-be-marked-immutable - 創建標記的函數不可改變的日期。 – 2012-02-14 13:58:23

+0

謝謝。優化到110毫秒!將等待如果解決方案沒有自定義函數存在=) – whatswrong 2012-02-14 14:49:40

3

如果用戶名是首要重點將是不同的,你不需要把迪stinct在它.. http://www.w3schools.com/sql/sql_primarykey.asp

和聚集的較受歡迎的鏈接索引在主鍵

+0

對不起,PK是在兩個字段(userid,login_date) – whatswrong 2012-02-14 13:49:59

+0

Ok,所以它是一個複合主鍵。 其中date_trunc('month',login_date)='01' 可以提高性能,並且UserID應該是主鍵,它在很多其他情況下也會幫助您。 – 2012-02-14 13:52:16

+0

實際上,表名是user_daily_activity。我將其重命名爲用戶,現在我發現我不應該這樣做。複合鍵是必要的 – whatswrong 2012-02-14 13:59:32

1

你可以嘗試這樣的事情?

select count(DISTINCT userid) 
from users 
where 
login_date >= '2012-01-12'::date and 
login_date < '2012-01-12'::date + '1month'::interval 

刪除有關索引列的表達式將使優化程序工作更輕鬆。

+0

當然,你需要在login_date上有一個索引來使它有效。 – gpeche 2012-02-14 14:43:32

+0

嗯,它工作速度很快140毫秒。但結果數據不同=) – whatswrong 2012-02-14 14:48:21

+0

我不是Postgresql的專家,你將不得不在日期範圍內工作。問題是:不要在你的索引列中放置表達式,所以優化器有一個明確的提示,你想使用該索引。 – gpeche 2012-02-14 14:51:58