在前端应用程序中使用Oracle中的游标是否有利?

时间:2013-02-19 05:42:49

标签: oracle plsql cursor

我的数据库中有两个表。每张表都有2000条记录。由于我有大量的记录,我想编写最优的代码来检索记录。 USER_DETAILS表是:

+---------+-----------+-----------+
| user_id | user_name | join_date |
+---------+-----------+-----------+

引用USER_DETAILS表的第二个表是:

+---------+-----------+-----------+
| user_id | fav_color | fav_dish  |
+---------+-----------+-----------+

我有两种方法:第一种:

SELECT UD.*,FAV.FAV_COLOR, FAV.FAV_DISH FROM USER_DETAILS UD, FAV_DETAILS FAV 
    WHERE UD.USER_ID = FAV.USER_ID;

第二种方法是编写一个PL / SQL程序:

DECLARE
CURSOR C1(X NUMBER) IS SELECT * FROM USER_DETAILS WHERE USER_ID = X;
CURSOR C2 IS SELECT * FROM USER_FAV;
Y NUMBER := &USER_ID;
BEGIN
FOR C IN C1(Y)
    LOOP
    DBMS_OUTPUT.PUT_LINE('USER DETAILS');
    DBMS_OUTPUT.PUT_LINE('----------------');
    FOR D IN C2
        LOOP
        IF C.DEPTNO = D.DEPTNO THEN
            DBMS_OUTPUT.PUT_LINE(RPAD(C.USER_ID,10)||RPAD(C.USER_NAME,10)||RPAD(D.FAV_COLOR,10));
        END IF;
    END LOOP;
END LOOP;
END;

哪种代码会提供更好的性能?为什么?我想获得用户的完整细节。

如果我使用游标,我会从服务器获取所有记录到SGA吗?我将在JSP页面中使用此数据库,该页面仅由移动设备访问。

由于移动设备中的互联网对我的目标用户来说非常慢(大约10KB),因此我担心带宽。在我看来,我发现执行连接将执行笛卡尔积并检查匹配结果,这将取出1000 * 1000条件中的一个条件,其中PL / SQL块中的检查条件仅为1000 + 1000。条件数量。但据我所知,光标将在客户端内存中创建一个阴影页面,它将创建表格。这意味着它将从服务器获取所有数据并存储在客户端中。我现在纠正了吗?

3 个答案:

答案 0 :(得分:1)

你可以阅读here Tom Kyte的口头禅:

  

如果可能,您应该在单个SQL语句中执行此操作   如果您无法在单个SQL语句中执行此操作,请在PL / SQL中执行此操作   如果您无法在PL / SQL中执行此操作,请尝试Java存储过程   如果您不能在Java中执行此操作,请在C外部过程中执行此操作   如果你不能在C外部程序中做到这一点,你可能想认真考虑为什么你需要这样做...

基本上通过使用plsql存储过程,您可以从sql引擎转发到plsql引擎。更重要的是,如果你有正确的索引并且你正确地构建了你的查询,那么sql优化器可能会比你更快。

Here is another good AskTom post

答案 1 :(得分:1)

一般使用单个select语句会有更好的表现 通过单个选择,您将访问RDBMS Sql引擎一次,RDMS将使用内部过程(索引,兑现查询......)提高性能。

以编程方式 (忽略内部RDMS功能)
在第一个查询中,您正在使用效率O(n)的顺序进行搜索 在第二个plsql语句中,通过使用嵌套循环,您正在以效率O(n ^ 2)的顺序进行搜索 search order of efficiency

答案 2 :(得分:0)

如果希望rsult的每一行都有一个指针,请执行光标以执行进一步的操作。如果您只需要select声明,只需执行select声明即可。光标将是一个矫枉过正。把事情简单化。