在 V3.2.3 BP2 版本后,OceanBase 数据库提供了新的 SQL 引擎来使用静态变量,避免重复进行变量、函数的评估,从而提升 SQL 的性能。如果 SQL 中保护 UDF,特别是谓词(WHERE 条件)中包含 UDF 的场景,设置 UDF 属性为 DETERMINISTIC 对使用新的 SQL 引擎至关重要。
本文以下面的 SELECT 为例,阐述 UDF 的 DETERMINISTIC 属性对性能的影响。
SELECT
USER_ID,
BILL_MONTH,
VALUE_TYPE,
CUMULATE_VALUE
FROM TB1
WHERE USER_ID >= 20 * 100000000000000
AND USER_ID <(20 + 1) * 100000000000000
AND MONTH_NUMBER = GET_MONTH(TO_NUMBER(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1), 'YYYYMM')))
;
表 TB1 为分区表,分区键为 MONTH_NUMBER。
CREATE TABLE "TB1" (
"USER_ID" NUMBER(16),
"BILL_MONTH" NUMBER(6),
"VALUE_TYPE" NUMBER(1),
"MONTH_NUMBER" NUMBER(2),
"CUMULATE_VALUE" NUMBER(12),
"USER_START_DAY" NUMBER(2)
) COMPRESS FOR ARCHIVE REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
partition by range("MONTH_NUMBER")
(partition P_R_01 values less than (2),
partition P_R_02 values less than (3),
partition P_R_03 values less than (4),
partition P_R_04 values less than (5),
partition P_R_05 values less than (6),
partition P_R_06 values less than (7),
partition P_R_07 values less than (8));
在 SELECT 语句中,分区键上的查询条件为。
MONTH_NUMBER = GET_MONTH(TO_NUMBER(TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1), 'YYYYMM')))
GET_MONTH 为 UDF,没有指定 DETERMINISTIC 属性,导致 SQL 执行计划生成时无法确定其对应的值,OceanBase 数据库无法进行分区裁剪,因而 SELECT 需要在所有分区上执行;当 UDF 定义为 DETERMINISTIC 时,SQL 优化器会将其视为常量,并在执行计划生成时直接用其对应的值进行分区的裁剪。
适用版本
OceanBase 数据库 V3.2.3 BP2 及之后版本。