Dizin

2013-07-11 17 views
7

'da kullanılan işlevi değiştirin. Altta yatan işlevi değiştirdiğimde bir işlev üzerine oluşturulmuş bir dizine ne olur?Dizin

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 
; 

Sonra bir dizin oluşturun::

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

Ama sonra yerine büyük harf harf kaldırmak için işlevini yeniden tanımlamak karar

Demek, bir işlev clean_name() olarak tanımlanır var. Oluşturduğum endekse ne oluyor? Kendi başına mı değişiyor? Yine DROP ve CREATE muyum? VACUUM [ANALYZE] [FULL]?

+1

Versiyondan bağımsız olarak cevaplarla ilgileniyorum. –

+2

Sonra belirtilmesi gereken - en iyi kullandığınız sürümle birlikte. –

cevap

6

IMMUTABLE araçları "değişmez" veya "un" değiştirilebilir". Bu kuralı ihlal etmekten kesinlikle kaçınmak için yapmanız gerekenler işlevini ve fonksiyonuna ve'a bağlı olan her şeyi düşürdüğünüzde yeniden oluşturun ve onu kullanan dizinleri yeniden oluşturun.

Yerinde işlevi yerine getirirseniz, sonuçlardan siz sorumlusunuz. Şahsen PostgreSQL'in IMMUTABLE işlevleri için OR REPLACE işlevini devre dışı bırakması gerektiğini düşünüyorum, bu nedenle ignore_immutable_checks_even_though_it_might_cause_incorrect_queries yapılandırma seçeneği gibi ekstra bir kasnaktan atlamanızı zorluyorum.

Bir değişmez işlevin davranışını değiştirirseniz, işleve bağlı dizinler geçersizdir. Sunucu, işlevin davranışının değişip değişmediğini söyleyemez; Her açıdan aynı davranışı olan optimize edilmiş bir sürümle değiştirmiş olabilirsiniz. Yani, sizin için dizinleri geçersiz kılmaz, belki de gerekir, çünkü eğer fonksiyonunuzun davranışı farklıysa, yanlış sorgu sonuçları işlevine bağlı sorgularda alabilirsiniz.

+0

_Sunucu, işlevin davranışının değişip değişmediğini söyleyemiyor. Bu, örneğin _inline_ işlevi örneğimde olduğu gibi olabilir. [Bu cevabı kontrol et] (http://www.postgresql.org/message-id/[email protected]) –

4

işlevi değiştirirseniz Endeksi yeniden zorunda kalacak (söz konusu işlevi yerine hala tweaked ama kararlı olması beklenen ediliyor değiştirmelerin oldukça uzun dizi kullanarak., Benzerdir). Üzerinde

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

Ve endeksi:

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

Basit fonksiyon ters tamsayı dönmek için

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

endeksi kullanılır:

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) 

Şimdi Tamsayı döndürmek için işlev değiştirildi tself:

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

Ve endeks artık kullanılmaz: endeksi

reindex index t_i_index; 

yeniden oluşturulur

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) 

ise tekrar kullanılır:

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

Tamam, beklenmedik değil. Bir 'REINDEX' de planlayıcıyı tekrar indeksi kullanmaya ikna edeceğini umuyorum, hayır? –

+0

@Dylan Evet reindex çalışır ve daha basittir. Cevabı güncelledim. –