你的數倉函數結果不穩定,多是屬性指定錯了

摘要:本文簡單介紹GaussDB(DWS)函數下推屬性的相關知識,並提供幾個函數屬性相關的典型案例供你們參考。

用戶在使用GaussDB(DWS)時,應該正確指定函數屬性,錯誤指定函數屬性不只會致使查詢語句執行效率低,並且可能會致使結果集不穩定的狀況。本文簡單介紹GaussDB(DWS)函數下推屬性的相關知識,並提供幾個函數屬性相關的典型案例供你們參考。node

1. 函數下推屬性介紹

GaussDB(DWS)建立函數時,能夠指定許多函數屬性,其中,與函數下推相關的屬性爲易失性級別 下推屬性,其中:sql

易失性:

  • IMMUTABLE:該屬性的函數不會修改數據庫,而且保證在任何狀況下一樣的輸入參數永遠返回一樣的結果;
  • STABLE:該屬性的函數不會修改數據庫,而且保證在同一個查詢中,對於一樣的輸入參數,函數返回的結果相同;
  • VOLATILE:該屬性的函數對於一樣的輸入參數,函數的返回結果可能不通,典型的如timeofday,建立函數時若是未明確指定,則默認爲VOLATILE;

下推屬性:

  • SHIPPABLE:函數能夠下推到DN執行
  • NOT SHIPPABLE:函數不能下推到DN執行,建立函數時若是未明確指定,則默認爲NOT SHIPPABLE。

在GaussDB(DWS)中,IMMUTABLE屬性的函數時必定可以下推到DN執行的,無論下推屬性是否爲SHIPPABLE,對於STABLE和VOLATILE屬性的函數,函數是否能下推要看指定的SHIPPABLE屬性。所以,在建立函數時若是同時指定了IMMUTABLE 和 NOT SHIPPABLE的屬性,函數建立成功時會有如下提示:數據庫

NOTICE:  Immutable function will be shippable anyway.

2. 函數下推屬性典型案例

案例一:未指定函數易失性級別致使函數不下推

函數定義以下:函數

create function try_cast_int(p_in text, p_default int default 0) returns int
as $$
begin
    begin
        return $1::int;
    exception
    when others then
        return p_default;
    end;
end;
$$
language plpgsql;

因爲建立函數時未明確指定函數易失性級別和函數屬性,函數默認爲VOLATILE NOT SHIPPABLE,使用該函數時執行計劃以下:post

postgres=# explain verbose select try_cast_int(b) from test order by a;
                                      QUERY PLAN                                      
--------------------------------------------------------------------------------------
 Sort  (cost=13.91..14.04 rows=50 width=36)
   Output: (try_cast_int(test.b, 0)), test.a
   Sort Key: test.a
   ->  Data Node Scan on "__REMOTE_SORT_QUERY__"  (cost=0.00..12.50 rows=50 width=36)
         Output: try_cast_int(test.b, 0), test.a
         Node/s: All datanodes
         Remote query: SELECT a, b FROM ONLY public.test WHERE true ORDER BY 1
(7 rows)

能夠看出該sql執行計劃不下推,執行效率較低,分析該函數發現該函數能夠指定爲IMMUTABLE屬性,讓該函數能夠下推,所以,能夠經過如下方式優化:性能

ALTER FUNCTION try_cast_int(text,int) IMMUTABLE;

案例二:錯誤指定了函數下推屬性致使結果集不穩定

下推函數可以下推到DN執行,與不下推函數相比有着更高的執行效率,有時開發者爲了加快函數執行效率,全部自定義函數建立時都會指定爲SHIPPABLE,某函數定義以下:優化

create function get_count() returns int
SHIPPABLE
as $$
declare
    result int;
begin
    result = (select count(*) from test);  --test表是hash表
    return result;
end;
$$
language plpgsql;

調用該函數發現如下現象:spa

postgres=# select get_count();
 get_count 
-----------
      2106
(1 row)

postgres=# select get_count() from t_src;
 get_count 
-----------
      1032
(1 row)

發現加上from表以後函數的返回值結果發生了變化!爲何會出現這種狀況呢?這是由於因爲這個函數指定了SHIPPABLE的函數屬性,所以生成計劃時該函數會下推到DN上執行,該函數下推到DN後,因爲函數定義中的test表是hash表,所以每一個DN上只有該表的一部分數據,因此select count(*) from test返回的結果不是test表全量數據的結果,而是每一個DN上部分數據的結果,所以致使加上from表後函數返回預期發生變化,優化方法:code

(1)將函數改成不下推:alter function get_count() not shippable;blog

(2)將函數中用到的表改成複製表,這樣每一個DN上都是一份該表的全量數據,即便下推到DN執行,也能保證結果集符合預期。

3. 總結

建立自定義函數時,要正確指定函數的屬性,確保函數屬性符合預期,防止因函數屬性設置不正確致使的性能降低或結果集不穩定。

 本文分享自華爲雲社區《GaussDB(DWS)函數下推屬性介紹》,原文做者:Arrow0lf。

點擊關注,第一時間瞭解華爲雲新鮮技術~

相關文章
相關標籤/搜索