返回首页

gbase数据、南大通用产品文档:GBase8aOLAP 开窗函数参数优化

更新日期:2024年09月11日

gbase 的开窗函数中sum、avg 运行性能随窗口大小变大而性能下降,可通过
调整参数gbase_buffer_rowset 的值来提升性能。gbase_buffer_rowset 表示保存中
间结果集的内存上限。

执行原理:
在进行olap 计算时,首先根据gbase_buffer_rowset 参数为计算过程分配保存
中间结果集的内存空间,将gbase_buffer_rowset 分成n 块,n 由最大线程数和
parallel_degree 决定,计算过程中可以使用这些buffer。然后由于计算过程中只保
存olap 列信息,
所以又将buffer 除以olap 列的列宽得到一个buffer 可以表示的行
数,此时,若存在一个partition 的行数超过一个buffer 保存行数的上限,超过的
部分保存在下一个buffer,而在窗口一行一行地滑动计算时,若一个partition 跨
buffer 保存,滑动过程中会跨buffer 访问数据,就会导致频繁的换入换出,换入
换出的次数最大能达到窗口的大小,所以,若窗口过大且存在较大的partition,
就会造成频繁的换入换出,造成性能损耗。

参数设置:

GBase 8a MPP Cluster 产品手册
5 数据库管理指南
文档版本953(2022-04-10)
南大通用数据技术股份有限公司
1292
提前评估数据表中最大的partition 的数据量,按照以下公式进行计算调整
gbase_buffer_rowset 的值,增加buffer 的内存,尽量在一个buffer 内保存最大的
partition,以尽量减少跨buffer 访问的次数。
max_partition_size*列宽(进行olap 函数计算的列,如sum(a),若a 列为double 类
型,则列宽为8)得到一个buffer 的值。然后再考虑gbase_parallel_degree 参数,
若degree 值为0,则将这个buffer 的值乘以最大线程数
gbase_parallel_max_thread_in_pool 的一半,
得到的结果向上取到2 的n 次方后
(如
1024,512 等),就得到一个比较适合的rowset 值。
若gbase_parallel_degree 参数不为0,则将buffer 的值乘以最大线程数
gbase_parallel_max_thread_in_pool,得到的结果向上取到2 的n 次方后,得到一
个比较合适的rowset 值。
最后重新set gbase_buffer_rowset。

总结:
if(dregree == 0)
max_partition_size*列宽*gbase_parallel_max_thread_in_pool/2 = rowset;
else
max_partition_size*列宽*gbase_parallel_max_thread_in_pool = rowset;
例如:
create table sales(
sales_employee varchar(50) not null,
fiscal_year varchar(50) not null,
sale decimal(14,2) not null,
primary key(sales_employee,fiscal_year)
);
select
fiscal_year,
sales_employee,
sale,
avg(sale) over (partition by sales_employee order by fiscal_year
ROWS BETWEEN 10000 PRECEDING AND 10000 FOLLOWING) total_sales
from sales;
加载数据4 千万;设置参数gbase_buffer_rowset=3073741824,执行性能较为稳定,
不会因窗口大小变化而性能波动。

GBase 8a MPP Cluster 产品手册
5 数据库管理指南
文档版本953(2022-04-10)
南大通用数据技术股份有限公司
1293

当看到在语法图表中引用例程参数列表时,使用例程参数列表段的适当部分。
语法
例程参数列表

参数


GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 1678
元素
描述
限制
语法
column
数据类型声明为
parameter 的列名
在指定表中必须存在
数据库对象

parameter UDR 的参数的名称
SPL 例程需要名称
标识符
table
包含 column 的表
表必须存在于数据库中
标识符
value
如果 UDR 调用对
parameter 没有值时缺
省使用
必须是和 parameter 相
同数据类型的文字,对于
不透明类型,必须定义一
个输入函数
精确数值
用法
参数是 UDR 声明中的形式参数。(接着调用一个带有参数的 UDR 时,必须用
实际参量代替参数,除非参数具有缺省值。)
参数名对于 GBase 8s 的外部例程是可选的。
当创建 UDR 时,为每个参数声明 name 和 data type。您可以直接指定数据类
型,或者使用 LIKE 或 REFERENCES 子句指定数据类型。您可以可选地指定缺
省值。
可以定义任意数量的 SPL 例程参数,但是传递给 SPL 例程的所有参数的总长度
必须小于 2 千兆字节。
在传递给以 Java™ 语言编写的 UDR 的参量中,不能有多于 9 个是 UDR 声明
为 Java 语言 BigDecimal 数据类型的 SQL DECIMAL 数据类型。
任何返回透明数据类型的 C 语言 UDR 必须在 C 主变量 var binary 声明中
指定 opaque_type。
SQL 数据类型的子集
连续和大对象数据类型作为参数是不合法的。UDR 可以声明一个在数据库中定义
过的任意数据类型的参数,包括除 BIGSERIAL 、BLOB 、BYTE 、CLOB 、
SERIAL 、SERIAL8 或 TEXT 以外的任何内置数据类型。
在 GBase 8s 中,参数也可以是复制数据类型或 UDT ,但复杂数据类型对于用
Java™ 语言编写的外部 UDR 的参数无效。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 1679
有关 GBase 8s 数据类型的信息,这些数据类型作为访问本地数据库外部表或视
图的例程的参数或返回值,请参阅从另一个数据库返回值。
使用 LIKE 子句
使用 LIKE 子句指定参数的数据类型,它与数据库中定义的列相同。如果
ALTER TABLE 语句改变列的数据类型,那么参数的数据类型也会改变。
在 GBase 8s 中,如果使用 LIKE 子句声明参数,就不能重载 UDR。例如,假设
您创建以下用户定义过程:
CREATE PROCEDURE cost (a LIKE tableX.colY, b INT)
. . .
END PROCEDURE;
在同一个 GBase 8s 数据库中不能创建另一个名为 cost( ) 的带有两个参数的过
程。然而,可以创建一个名为 cost( ) 带有一个参数而不是两个参数的过程。(另
一种克服 LIKE 子句限制的方法是通过用户定义的数据类型。)
使用 REFERENCES 子句
使用 REFERENCES 子句指定包含 BYTE 或 TEXT 数据的参数。REFERENCES
关键字允许您使用 BYTE 或 TEXT 对象的指针作为参数。如果在
REFERENCES 子句中使用 DEFAULT NULL 选项,并且不带参数地调用
UDR ,那么 NULL 值就用作缺省值。
使用 DEFAULT 子句
使用 DEFAULT 关键字后面跟一个表达式自动参数的缺省值。如果为参数提供缺
省值,并且以少于 UDR 定义的参量来调用这个 UDR 时,就是要缺省值。如果
不为参数提供缺省值,并且以少于 UDR 定义的参数来调用这个 UDR 时,调用
应用程序会收到错误。
下面的示例显示了 CREATE FUNCTION 语句,它为参数指定了缺省值。这个函数查
找参数 i 的平方。如果函数调用时不指定 i 参数的参量,数据库服务器使用 0
作为参数 i 的缺省值。
CREATE FUNCTION square_w_default
(i INT DEFAULT 0) {Specifies default value of i}
RETURNING INT; {Specifies return of INT value}
DEFINE j INT; {Defines routine variable j}

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 1680
LET j = i * i; {Finds square of i and assigns it to j}
RETURN j; {Returns value of j to calling module}
END FUNCTION;
警告: 当指定一个日期值作为参数的缺省值时,必须确保对年份指定 4 位数而
不是 2 位数字。当指定 2 位数字的年份时,环境变量 DBCENTURY 的设置会
影响数据库服务器如何解释日期值,所以 UDR 可能不使用希望的缺省值。有关
更多信息,请参阅 GBase 8s SQL 参考指南。
为用户定义例程指定 OUT 参数
注册一个 GBase 8s 的用户定义的例程时,可以使用关键字 OUT 来指定列表中
的任何一个参数是 OUT 参数。每个 OUT 参数对应例程通过指针直接返回的一
个只。例程通过指针返回的值是显式返回的任何值以外的一个额外值。
在注册了带有一个或多个 OUT 参数的用户定义函数以后,可以在 SQL 语句中
把函数和语言-局部变量(SLV)一起使用。(关于语句-局部变量的信息,请参阅
语句本地的变量表达式。)
如果指定了任何 OUT 参数,并且使用 GBase 8s 样式的参数,参量会通过引用
传递给 OUT 参数。OUT 参数在确定例程特征符时没有意义。
例如,下面对 C 用户定义函数的声明允许通过参数 y 返回一个额外值:
int my_func( int x, int *y );
用 CREATE FUNCTION 语句注册一个 C 函数与此类似:
CREATE FUNCTION my_func( x INT, OUT y INT )
RETURNING INT
EXTERNAL NAME "/usr/lib/local_site.so"
LANGUAGE C
END FUNCTION;
下一个示例中,该 Java™ 方法通过传递返回一个额外值:
public static String allVarchar(String arg1, String[] arg2)
throws SQLException
{
arg2[0] = arg1;
return arg1;
}

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 1681
要将这作为 UDF 注册,请使用与以下示例相似的语句:
CREATE FUNCTION all_varchar(VARCHAR(10), OUT VARCHAR(7))
RETURNING VARCHAR(7)
WITH (class = "jvp")
EXTERNAL NAME 'gbasedbt.testclasses.jlm.Param.allVarchar(java.lang.String,
java.lang.String[ ])'
LANGUAGE JAVA;
为用户定义的例程指定 INOUT 参数
用 SPL 、C 或 Java™ 语言编写的 UDR 也可以支持 INOUT 参数。
当调用 UDR 时,每个 INOUT 参数的值作为参量通过引用传递给
UDR 。
当 UDR 执行完成时,它能够为 INOUT 参数返回一个修改后的值给调用上下
文。INOUT 参数可以是 GBase 8s 支持的任意数据类型,包括用户定义的和复杂
数据类型和以下例外:

Serial 类型(BIGSERIAL 、SERIAL 和 SERIAL8)

简单大对象类型(BYTE 和 TEXT)。
在以下示例中,CREATE PROCEDURE 语句注册一个带有单个 INOUT 参数的
C 例程:
CREATE PROCEDURE CALC ( INOUT param1 float )
EXTERNAL NAME "$GBASEDBTDIR/etc/myudr.so(calc)"
LANGUAGE C;
SPL 例程可以调用具有 OUT 和 INOUT 参数的其它 UDR,如果这些 UDR 用
SPL 或 C 语言编写。然而,SPL 例程不能调用参量包含 OUT 或 INOUT 参数
的 Java UDR。
支持从 SPL 例程调用具有命名或未命名 ROW 参数的 UDR ,对 ROW 参数类
型和调用的 UDR 的编程语言有以下依赖性:
SPL 例程可以调用 ROW 参量是 IN 参数的 C UDR。但是不能调用 ROW 参量
是 OUT 或 INOUT 参数的 C UDR 。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 1682
SPL 例程可以调用具有任意参数类型(包括 IN 、OUT 和 INOUT)的 ROW
参量的 SPL UDR。
可以将 INOUT 参数分配给语句-局部变量(SLV),语句-局部变量在语句本地的
变量表达式部分中描述。

SQLExtendedFetch 扩展 SQLFetch 的功能。
SQLExtendedFetch 通过以下方式扩展功能:

GBase 8s ODBC Driver 程序员指南
南大通用数据技术股份有限公司
- 223 -
 为每个绑定列返回数组形式的行集数据(一行或多行)。
 根据滚动类型参数的设置滚动结果。
SQLExtendedFetch 与 SQLSetStmtOption 一起使用。
要一次向前获取一行数据,应用程序会调用 SQLFetch。
下表描述了 SQLExtendedFetch 的 SQLSTATE 和错误值。
SQLSTATE
错误值
错误消息
01000
-11001
General warning
01004
-11003
Data truncated
01S01
-11006
Error in row
07006
-11013
Restricted data type attribute violation
08S01
-11020
Communication-link failure
22002
-11024
Indicator value required but not supplied
22003
-11025
Numeric value out of range
22005
-11026
Error in assignment
22008
-11027
Datetime field overflow
22012
-11028
Division by zero
24000
-11031
Invalid cursor state
40001
-11037
Serialization failure
S1000
-11060
General error
S1001
-11061
Memory-allocation failure
S1002
-11062
Invalid column number
S1008
-11065
Operation canceled
S1010
-11067
Function-sequence error
S1106
-11086
Fetch type out of range
S1107
-11087
Row value out of range
S1C00
-11092
Driver not capable
S1T00
-11094
Time-out expired
08S01
-11301
A protocol error has been detected. Current connection is
closed.
S1000
-11307
In SQLExtendedFetch, only SQL_FETCH_NEXT is
supported for SQL_SCROLL_Forward_only cursors

如果发生与整个行集相关的错误,例如 SQLSTATE S1T00 (超时),则驱动程序返回
SQL_ERROR 和适当的 SQLSTATE。行集缓冲区的的内容未定义,游标位置不变。

GBase 8s ODBC Driver 程序员指南
南大通用数据技术股份有限公司
- 224 -
如果发生与单个行相关的错误,则驱动程序执行以下操作:

将行 rgfRowStatus 数组中的元素设置为 SQL_ROW_ERROR

在错误队列中发布 SQLSTATE 01S01(行中的错误)

在错误队列中的 SQLSTATE 01S01(行中的错误)之后,发布零个或多个附加的
SQLSTATE 值
驱动程序处理错误或警告之后,它继续行集中剩余的操作,并返回
SQL_SUCCESS_WITH_INFO。因此,对于与单个行相关的每个错误,错误队列包含
SQLSTATE 01S01(行中的错误),后跟零个或多个附加的 SQLSTATE 值。
驱动程序处理该错误之后,
它访存行集中的剩余的行,
并返回 SQL_SUCCESS_WITH_INFO。
因此,对于返回错误的每一行,错误队列包含 SQLSTATE 01S01(行中的错误),后跟零
个或多个附加的 SQLSTATE 值。
如果行集包含已经访存的行,则当首次访存行时,驱动程序不需要返回错误的 SQLSTATE
值。但是,对于最初返回错误的每一行,它需要返回 SQLSTATE 01S01(行中的错误),
和 SQL_SUCCESS_WITH_INFO。例如,维护高速缓存的静态游标可能会缓存行状态信息
(因此,它可以确定哪一行包含错误),但是不能缓存与错误相关的 SQLSTATE。
错误行不会影响相关游标的移动。例如,假定结果集大小为 100,行集大小为 10。如果当
前行集是从 11 到 20 的行,并且 11 行的 rgfRowStatus 数组中的元素是
SQL_ROW_ERROR,则使用 SQL_FETCH_NEXT 访存类型调用 SQLExtendedFetch 仍然
返回 21 到 30 行。
如果驱动程序返回任何警告,例如 SQLSTATE 01004(数据截断),则在返回适用于整个
行或行集中位置行的警告,然后返回特定行的错误信息。它返回关于这些行的任何其它错
误信息的特定行的警告。