我在oracle pl sql中有一段代码,想真正了解一下有多少上下文切换
If x=0 then
curserx= select a from mytable1;
Else
curserx=select a from mytable1 where id=:x;
End;
Loop
Fetch on cursorx
Select c from mytable2 where a=curserx.a;
End loop;
Run Code Online (Sandbox Code Playgroud)
这只是一个示例代码,所以请原谅任何文本大小写和逻辑错误。
我将您的伪代码转换为 PL/SQL 并包含注释,表明我相信您将在何处进行从 PL/SQL 引擎到 SQL 引擎的上下文切换。
请注意,如果您要查询大量行,则可以使用 FETCH BULK COLLECT INTO 并在每次提取时检索多行,从而大大减少上下文切换。
DECLARE
l_x_value INTEGER;
l_cursor SYS_REFCURSOR;
l_fetched mytble1.a%TYPE;
BEGIN
/* context switch to open */
IF x = 0
THEN
OPEN l_cursor FOR SELECT a FROM mytable1;
ELSE
OPEN l_cursor FOR
SELECT a
FROM mytable1
WHERE id = l_x_value;
END IF;
LOOP
/* context switch per fetch */
FETCH l_cursor INTO l_fetched;
EXIT WHEN l_cursor%NOTFOUND;
/* context switch for implicit cursor */
SELECT c
INTO l_fetched
FROM mytable2
WHERE a = curserx.a;
END LOOP;
/* context switch to close */
CLOSE l_cursor;
END;
Run Code Online (Sandbox Code Playgroud)
但这还不是全部!请记住,上下文切换是双向的:SQL -> PL/SQL 和 PL/SQL -> SQL。您可以通过使用 UDF pragma (12c+) 声明函数或使用 WITH FUNCTION 子句(也是 12c+)定义函数来减少从 SQL 到 PL/SQL 的开销。仍然有一个上下文切换,但一些工作是在编译时而不是运行时完成的。
所以在下面的代码中,对于从 SELECT 中调用函数的每次,都有一个开关。
CREATE OR REPLACE FUNCTION full_name (first_in IN VARCHAR2,
last_in IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN first_in || ' ' || last_in;
END;
/
DECLARE
l_name VARCHAR2 (32767);
BEGIN
SELECT full_name (first_name, last_name) INTO l_name
FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE (l_name);
END;
/
Run Code Online (Sandbox Code Playgroud)
最后一个警告:您应该尽一切努力避免在随后从 SQL 调用的函数中执行 SQL。适用于您的 SQL 语句的标准读取一致性模型不会“带入”到函数的 SQL 中。换句话说,如果您“外部” SELECT 在 10:00 开始运行并运行一个小时,并且在 10:05,有人会从外部查询和函数中的查询中使用的表中删除行(和提交),这两个查询将使用这些表的不同状态。
| 归档时间: |
|
| 查看次数: |
2618 次 |
| 最近记录: |