2016-03-01 63 views
1

我想在Postgres中添加一個帶有WHERE子句的索引。我用下面的查詢做到這一點:如何在Postgres中添加帶WHERE子句的索引

create index concurrently em_openorder_idx on line (m_product_id, org_id, date) where date >= now() - 90 

但我收到以下錯誤:

functions in index predicate must be marked IMMUTABLE 
+0

您無法爲最近90天的索引編制索引 - 這就是錯誤的含義。只需索引所有數據。 –

+0

你能詳細說明你想做什麼嗎?看起來像一個[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) –

+0

行是一個大表,所以我想用daterange創建索引。當我們創建索引時,它將擁有隻有90天記錄的虛擬表。所以查詢會更快@JuanCarlosOropeza –

回答

0

只需創建

create index concurrently em_openorder_idx on line (m_product_id,org_id,date) 

我客串,你想實現類似的查詢索引到此

EXPLAIN ANALYZE 
SELECT * 
FROM line 
WHERE m_product_id = @id 
    AND date>=now()-90 

這將使用索引,並且應該非常快。

+0

在這裏,它會從完整的表格中選擇我不期望的表格,因爲表格很大 –

+0

不可以,索引會過濾掉你的行。如果在我剛剛編輯時添加了'EXPLAIN ANALYZE',則可以在查詢計劃中看到索引如何過濾數據。 –

+0

是日期字段的時間戳或日期字段?在where子句中,你可以使用current_date函數而不是now() –

1

WHERE子句中的表達式必須是immutable,即對於給定的參數集,每次調用它時都必須返回相同的值。 now()顯然不符合資格。

你可以索引最近90天的數據是這樣的:

create index concurrently em_openorder_idx on line (m_product_id,org_id,date) 
where date>='now'::date-90 

但是,如果你回頭看看索引定義,你會看到,它已經變成了一個常量表達式:

... WHERE date >= ('2016-03-02'::date - 90); 

換句話說,這90天的窗口不會隨着時間的推移自動前進;您將需要定期刪除並自己重新創建此索引。

需要注意的另一件事是,如果您的查詢將date與不可變表達式進行比較,那麼您的查詢只能使用此索引。例如,該指數將在這裏使用:

SELECT * FROM line WHERE date = '2016-03-02'; 

...但不能用在這裏:

SELECT * FROM line WHERE date = CURRENT_DATE; 

順便說一句,如果你對Postgres的9.5,這表可能是BRIN index的合適人選。

+0

我反對最後一個語句,current_date將使用該特定查詢中的索引 –

+0

@LongBeard_Boldy:它不會;看到這個[SQLFiddle](http://sqlfiddle.com/#!15/185f1/2) –

+0

對不起,我的壞。當然,如果使用部分索引,那麼where子句中不會使用索引的非不可變函數進行查詢。但是,如果您將索引整列,策劃者將使用該索引。 –