
# 带自定义函数的语句不下推
#### 问题现象
SQL语句不下推。
#### 原因分析
目前DWS可以支持绝大多数常用函数的下推，不下推函数的场景主要出现在自定义函数属性定义错误的情况下。
不下推语句的执行方式没有利用分布式的优势，其在执行过程中，相当于把大量的数据和计算过程汇集到一个节点上去做，因此性能通常非常差。
#### 分析过程
1. 通过EXPLAIN VERBOSE打印语句执行计划。 
   ![](https://support.huaweicloud.com/trouble-dws/figure/zh-cn_image_0000001119918202.png "点击放大")
   上述执行计划中出现__REMOTE关键字，表示当前的语句为不下推执行。
   
   
2. 不下推语句在pg_log中会打印不下推的原因，上述语句在CN的日志中会找到类似以下的日志。 
   ![](https://support.huaweicloud.com/trouble-dws/figure/zh-cn_image_0000001163563161.png "点击放大")
   
   
 
#### 处理方法
审视用户自定义函数的provolatile属性是否定义正确。如果定义不正确，要修改对应的属性，使它能够下推执行。
具体判断方法可以参考如下说明：
- 函数相关的所有属性都在[pg_proc](https://support.huaweicloud.com/devg-dws/dws_04_0608.html)系统表中可以查到，与函数能否下推相关的两个属性是provolatile和proshippable：
  - 如果函数的provolatile属性为i，则无论proshippable的值是否为t，则函数始终可以下推。
  
  - 如果函数的provolatile属性为s或v，则仅当proshippable的值为t时，函数可以下推。
   
- provolatile的本质含义是描述函数的易变属性，取值为i/s/v。i代表IMMUTABLE，s代表STABLE，v代表VOLATILE。 例如：
  - 如果一个函数对于同样的输入，一定有相同的输出，那么这类函数就是IMMUTABLE的。例如，绝大部分的字符串处理函数，这类函数始终可以下推。
  
  - 如果一个函数的返回结果在一个SQL语句的调用过程中，结果是相同的，那么它就是STABLE的。例如，时间相关的处理函数，它的最终显示结果可能与具体的GUC参数相关（例如控制时间显示格式的参数），这类函数都是STABLE的，此类函数仅当其属性是SHIPPABLE的时候，才能下推。
  
  - 如果一个函数的返回结果可能随着每一次的调用而返回不同的结果。例如，nextval、random这种函数，每次调用结果都是不可预期的，这类函数就是VOLATILE的，此类函数仅当其属性是SHIPPABLE的时候，才能下推。
   
- proshippable字段表示函数是否可以下推到DN上执行，默认值是false，取值范围为t/f/NULL。
 
