使用Oracle临时表进行多个异步HTTP调用

时间:2010-11-24 16:34:41

标签: oracle .net-4.0 silverlight-3.0

我有一个Silverlight应用程序,可以对Oracle数据库进行多次(通常是并发的)异步调用。最大的数据库表存储了大约500万条记录。以下是Silverlight应用程序如何工作的摘要,然后是我的问题。

  1. 用户设置查询条件以选择特定的记录组,通常是组中的500到5000条记录。

  2. 对数据库进行异步WCF调用,以检索所选记录组中四个字段(纬度,经度,标题和时间偏移)中的值(意味着调用返回从2k到20k浮动的任何位置)点数。这些值用于在浏览器中绘制地图上的点。

  3. 从这里,用户可以选择在与初始记录组相关联的另外20个左右的字段中的一个或多个中绘制值。用户单击字段名称,并进行另一个异步WCF调用以检索字段值。

  4. 我的问题是:在这种情况下,将第一步中选择的记录存储在临时表(或物化视图)中是否有意义,以加快和简化第三步中的数据访问? /强>

    如果是这样,有人可以给我一个关于维护用户会话的浏览器到临时表链接的好方法的提示吗?

    现在,每次用户选择一个新的字段进行绘图时,我只是重新查询500万个点 - 直到用户一次选择三个或更多字段为止。这会导致异步调用在返回之前超时。

2 个答案:

答案 0 :(得分:1)

当我第一次阅读本文时,我想到了'全球临时表'(gtt),并意识到这对你丝毫没有帮助!这是因为GTT中的数据仅在会话中可见,并且对于无状态Web应用程序,可能使用连接池,应用程序用户和数据库会话之间没有保证关系(一个用户可能在连续的连接上交给不同的会话,一个会话将交给几个不同的用户)。现在临时表应该可以解决问题。

似乎在每次迭代命中时,人(通过silverlight)轮询相同的数据(并且需要大量启动)。

我相信临时表就足够了。这是一个问题,展示了如何在Web环境中执行此操作。请记住,数据存储的那一刻它已经老化并且可能过时,需要进行清理工作。 http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:76812348057

现在要将它与用户联系起来,而不是100%确定如何在Silverlight中执行此操作(假设通过asp.net?)是在进行程序化之前进行身份验证的用户?如果是这样,你应该能够获取他们的凭据并将其用作查询源(利用他们的用户名和/或SID作为他们的主键,并将其外键与数据表一起使用,如asktom链接中所述)。 http://www.codeproject.com/KB/silverlight/SL3WindowsIdentityName.aspx 此链接似乎显示如何在窗口的身份验证方案中获取当前的silverlight用户。

HTH

答案 1 :(得分:1)

我们可以使用CONTEXT来完成此操作。这是会话内存中的命名空间,我们可以使用它来存储值。 Oracle带有一个默认命名空间'USERENV',但我们可以定义自己的命名空间。上下文必须由具有CREATE ANY CONTEXT权限的用户创建;这通常是DBA。该语句引用了一个PACKAGE,它在命名空间中设置和获取值,但是为了使语句成功,该包不一定存在:

SQL> create context user_ctx using apc.ctx_pkg
  2  /

Context created.

SQL>

现在让我们创建一个包:

SQL> create or replace package ctx_pkg
  2  as
  3      procedure set_user_id(p_userid in varchar2);
  4      function get_user_id return varchar2;
  5      procedure clear_user_id;
  6  end ctx_pkg;
  7  /

Package created.

SQL>

有三种方法可以在命名空间中设置,获取和取消设置值。请注意,我们可以使用一个命名空间来保存不同的valiables。我只是使用这个包在USER_CTX命名空间中设置一个变量(USER_ID)。

SQL> create or replace package body ctx_pkg
  2  as
  3      procedure set_user_id(p_userid in varchar2)
  4      is
  5      begin
  6         DBMS_SESSION.SET_CONTEXT(
  7          namespace  => 'USER_CTX',
  8          attribute  => 'USER_ID',
  9          value      => p_userid);
 10      end set_user_id;
 11
 12      function get_user_id return varchar2
 13      is
 14      begin
 15          return sys_context('USER_CTX', 'USER_ID');
 16      end get_user_id;
 17
 18      procedure clear_user_id
 19      is
 20      begin
 21         DBMS_SESSION.CLEAR_CONTEXT(
 22          namespace  => 'USER_CTX',
 23          attribute  => 'USER_ID');
 24      end clear_user_id;
 25
 26  end ctx_pkg;
 27  /

Package body created.

SQL>

那么,这怎么解决?这是一个临时存储数据的表。我将添加一个列,该列将包含一个标记以标识用户。当我们填充表格时,此列的值将由CTX_PKG.GET_USER_ID()提供:

SQL> create table temp_23 as select * from big_table
  2  where 1=0
  3  /

Table created.

SQL> alter table temp_23 add (user_id varchar2(30))
  2  /

Table altered.

SQL> create unique index t23_pk on temp_23(user_id, id)
  2  /

Index created.

SQL>

...在那张桌子上我创建了一个视图:...

create or replace view v_23 as
select 
         id
        , col1
        , col2
        , col3
        , col4
from temp_23
where user_id = ctx_pkg.get_user_id
/

现在,当我想在表格中存储一些数据时,我需要使用唯一标识我的用户的值设置上下文。

SQL> exec ctx_pkg.set_user_id('APC')

PL/SQL procedure successfully completed.

SQL>

此语句使用20个随机行填充临时表:

SQL> insert into temp_23
  2  select * from
  3      ( select b.*, ctx_pkg.get_user_id
  4        from big_table b
  5        order by dbms_random.random )
  6  where rownum <= 20
  7  /

20 rows created.

SQL>

我可以通过查询视图来检索这些行。但是,当我更改我的USER_ID并运行相同的查询时,我再也看不到它们了:

SQL> select * from v_23
  2  /

        ID       COL1 COL2                           COL3            COL4
---------- ---------- ------------------------------ --------- ----------
    277834       1880 GV_$MAP_EXT_ELEMENT            15-OCT-07       4081
    304540      36227 /375c3e3_TCPChannelReaper      15-OCT-07         36
   1111897      17944 /8334094a_CGCast               15-OCT-07         17
   1364675      42323 java/security/PublicKey        15-OCT-07         42
   1555115       3379 ALL_TYPE_VERSIONS              15-OCT-07          3
   2073178       3355 ALL_TYPE_METHODS               15-OCT-07          3
   2286361      68816 NV                             15-OCT-07         68
   2513770      59414 /5c3965c8_DicomUidDoc          15-OCT-07         59
   2560277      66973 MGMT_MNTR_CA                   15-OCT-07         66
   2700309      45890 /6cc68a64_TrustManagerSSLSocke 15-OCT-07         45
   2749978       1852 V_$SQLSTATS                    15-OCT-07       6395
   2829080      24832 /6bcb6225_TypesTypePair        15-OCT-07         24
   3205157      55063 SYS_NTsxSe84BlRX2HiXujasKy/w== 15-OCT-07         55
   3236186      23830 /de0b4d45_BaseExecutableMember 15-OCT-07         23
   3276764      31296 /a729f2c6_SunJCE_n             15-OCT-07         31
   3447961      60129 HHGROUP                        15-OCT-07         60
   3517106      38204 java/awt/im/spi/InputMethod    15-OCT-07         38
   3723931      30332 /32a30e8e_EventRequestManagerI 15-OCT-07         30
   3877332      53700 EXF$XPVARCLST                  15-OCT-07         53
   4630976      21193 oracle/net/nl/NetStrings       15-OCT-07         21

20 rows selected.

SQL> exec ctx_pkg.set_user_id('FOX_IN_SOCKS')

PL/SQL procedure successfully completed.

SQL> select * from v_23
  2  /

no rows selected

SQL>

所以,挑战是:

  1. 建立一个可以自动用于唯一标识用户的令牌
  2. 在连接代码中找到一个钩子,可以在每次用户获得会话时设置上下文
  3. 同样重要的是,在你的断开代码中找到一个钩子,每次用户离开会话时都可以取消设置上下文
  4. 此外,请务必在用户完成后清除表格。