WEB开发网
开发学院数据库DB2 SQL过程的性能:提示和技巧 阅读

SQL过程的性能:提示和技巧

 2009-12-12 14:59:16 来源:WEB开发网   
核心提示:只有不可删除的游标才可以进行行分块,这就是为什么让 DB2 了解将如何使用游标是很重要的原因,SQL过程的性能:提示和技巧(3),通过在 SELECT 语句中指定 FOR READ ONLY 子句,可以将游标显式地声明为不可删除,正如本节标题所展示的,当您只是从数据库抽取数据而不执行任何更改时,或者通过在 SELECT

只有不可删除的游标才可以进行行分块。这就是为什么让 DB2 了解将如何使用游标是很重要的原因。通过在 SELECT 语句中指定 FOR READ ONLY 子句,可以将游标显式地声明为不可删除,或者通过在 SELECT 语句中使用 FOR UPDATE 子句将其声明为可删除。根据该信息(并且还根据下面描述的 BLOCKING 选项),DB2 将确定是否将行分块用于给定的游标。

缺省情况下,对于那些使用 FOR READ ONLY 子句定义的游标,DB2 将始终使用行分块,除非指定了 BLOCKING NO 绑定选项。另一方面,如果使用了 BLOCKING ALL 绑定选项,那么对于含混游标(既不是定义成 FOR READ ONLY 也不是定义成 FOR UPDATE 的游标),DB2 将使用行分块。

简而言之:如果可能,则在游标定义中使用 FOR READ ONLY 子句;如果您的过程包含含混游标,那么请使用 BLOCKING ALL 绑定选项。要设置 BLOCKING 绑定选项的值,我们还可以使用 DB2_SQLROUTINE_PREPOPTS 注册表变量。例如,要将 SQL 过程的隔离级别设置为未提交的读,并将行分块设置为 BLOCKING ALL,请使用下面这条命令:

db2set DB2_SQLROUTINE_PREPOPTS="ISOLATION UR BLOCKING ALL"

对于返回大型结果集的过程而言,分块特别重要。

通过使用 DB2_SQLROUTINE_PREPOPTS 注册表,还可以为存储过程指定其它绑定选项。

在无副作用的情况下,请使用 SQL 函数

正如我们在简介中提及的,SQL 过程和 SQL 函数是使用不同技术实现的。SQL 过程中的查询是单独编译的,每个查询都成为包中的一个节。编译是在过程创建时进行的,直到重新创建过程或者直到重新绑定其相关的包时才重新编译这些查询。

另一方面,SQL 函数中的查询是一起编译的,就好象函数体是一个查询一样。每当编译一条使用 SQL 函数的语句时,也会对 SQL 函数进行编译。

与 SQL 过程中所发生的情况不同,SQL 函数中的过程语句与数据流语句是在同一个层中执行的。因此,每当控制从过程语句流向数据流语句或相反时,并不发生上下文切换。

因为存在这些区别,所以当给定的过程代码段作为函数实现时的执行速度通常比作为过程实现时要快。但是,当然了,有一个小问题。函数只能包含那些不会改变数据库状态的语句(例如 INSERT、UPDATE 或 DELETE 语句是不允许的)。并且只允许完整 SQL PL 语言的子集出现在 SQL 函数中(不能是 CALL 语句、游标和条件处理)。

尽管有这些限制,但大多数 SQL 过程都可以在无副作用的情况下转换成 SQL 函数。例如,下面的过程:

CREATE PROCEDURE GetPrice (IN Vendor CHAR(20),
IN Pid INT,
OUT price DECIMAL(10,3))
LANGUAGE SQL
BEGIN
IF Vendor = 'Vendor 1' THEN
SET price = (SELECT ProdPrice
FROM V1Table WHERE Id = Pid);
ELSE IF Vendor = 'Vendor 2' THEN
SET price = (SELECT Price
FROM V2Table WHERE Pid = GetPrice.Pid);
END IF;
END

等同于下面的函数:

CREATE FUNCTION GetPrice (Vendor CHAR(20), PId INT)
RETURNS DECIMAL(10,3)
LANGUAGE SQL
BEGIN
DECLARE price DECIMAL(10,3);
IF Vendor = 'Vendor 1' THEN
SET price = (SELECT ProdPrice
FROM V1Table WHERE Id = Pid);
ELSE IF Vendor = 'Vendor 2' THEN
SET price = (SELECT Price
FROM V2Table WHERE Pid = GetPrice.Pid);
END IF;
RETURN price;
END

请注意,尽管使用了 CALL 语句来调用过程,但还需要使用 VALUES 语句从命令行调用函数:

VALUES (GetPrice('IBM', 324))

另一方面,与过程不同的是,您可以在允许表达式的任何上下文中调用函数:

SELECT VName FROM Vendors WHERE GetPrice(Vname, Pid) < 100;
SET price = GetPrice(Vname, Pid);

因此,正如本节标题所展示的,当您只是从数据库抽取数据而不执行任何更改时,请考虑使用 SQL 函数而不是使用 SQL 过程。

上一页  1 2 3 4  下一页

Tags:SQL 过程 性能

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接