2013-07-11 47 views
7

當我更改基礎函數時,構建在函數上的索引會發生什麼變化?替換索引中使用的函數

說,我有一個函數clean_name()定義爲:

CREATE OR REPLACE FUNCTION clean_name(n text) 
RETURNS TEXT AS 
$BODY$ 
DECLARE 
rec TEXT; 
BEGIN 
EXECUTE 
    'SELECT Regexp_replace(' || quote_literal(n) || ', ''[a-z]'', '''', ''g'');' 
INTO rec; 
RETURN rec; 
END; 
$BODY$ LANGUAGE plpgsql IMMUTABLE 
; 

然後創建一個索引:

CREATE INDEX my_table_upper_name_btree 
ON schema.my_table USING GIST (my_text_field); 

但後來我決定要重新定義函數刪除大寫字母來代替。我創建的索引會發生什麼?它是否自行改變?我是否再次使用DROPCREATEVACUUM [ANALYZE] [FULL]

(有問題的功能類似,使用替代相當長的一系列仍在微調,但預計將穩定替代品的。)

+1

我對答案感興趣,無論版本。 –

+2

然後需要說明 - 最好伴隨着您實際使用的版本。 –

回答

6

IMMUTABLE手段「不變」或「不變」多變」。你必須做的,以嚴格規避違反該規則是下降該功能和一切取決於它然後重新創建它和使用它的索引。

如果您在原地替換該功能,您將對後果負責。我個人認爲PostgreSQL應該不允許OR REPLACEIMMUTABLE函數出於這個原因,迫使你跳過像設置ignore_immutable_checks_even_though_it_might_cause_incorrect_queries配置選項的額外hoop。

如果更改不可變函數的行爲,則基於函數的索引無效。服務器無法判斷函數的行爲是否已經改變;你可能只是用一個在各方面都具有相同行爲的優化版本來替代它。因此,它不會使索引無效,但也許它應該,因爲如果你的函數的行爲不同,你可以得到不正確的查詢結果查詢基於函數。

+0

_服務器無法判斷函數的行爲是否發生了變化_函數爲_inline_時,可以像我的例子那樣。 [檢查這個答案](http://www.postgresql.org/message-id/[email protected]) –

4

如果你改變了功能,你將不得不重建索引。

create table t (i integer); 
insert into t (i) 
select generate_series(1, 100000); 
analyze t; 

一個簡單的函數來返回相反整數:在其上

create or replace function f(i integer) 
returns integer as $$ 
select i * -1; 
$$ immutable language sql; 

和索引:

create index t_i_index on t(f(i)); 

索引用於:

explain select * from t order by f(i); 
           QUERY PLAN         
--------------------------------------------------------------------------- 
Index Scan using t_i_index on t (cost=0.00..3300.26 rows=100000 width=4) 

現在函數更改爲返回整數i自行宣佈:

create or replace function f(i integer) 
returns integer as $$ 
select i; 
$$ immutable language sql; 

和索引不再使用:

explain select * from t order by f(i); 
          QUERY PLAN       
--------------------------------------------------------------- 
Sort (cost=11116.32..11366.32 rows=100000 width=4) 
    Sort Key: i 
    -> Seq Scan on t (cost=0.00..1443.00 rows=100000 width=4) 

如果索引重建

reindex index t_i_index; 

它再次被使用:

explain select * from t order by f(i); 
           QUERY PLAN         
--------------------------------------------------------------------------- 
Index Scan using t_i_index on t (cost=0.00..4376.26 rows=100000 width=4) 
+0

好的,並不意外。我預計'REINDEX'也會說服規劃者再次使用該指數,不是嗎? –

+0

@Dylan是reindex工作,更簡單。我已經更新了答案。 –