【问题标题】:Using Oracle temp table for multiple async HTTP calls使用 Oracle 临时表进行多个异步 HTTP 调用
【发布时间】:2010-11-26 01:18:41
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

    标签: oracle .net-4.0 silverlight-3.0


    【解决方案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>
    

    共有三种方法来设置、获取和取消设置命名空间中的值。请注意,我们可以使用一个命名空间来保存不同的变量。我只是使用这个包在 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. 同样重要的是,在您的断开连接代码中找到一个挂钩,该挂钩可以在用户每次离开会话时取消设置上下文

    另外,请记住在用户完成表格后清除表格。

    【讨论】:

    • 感谢您非常彻底的回答!显然,在我尝试实施之前,我不会知道它的效果如何,但在略读它时,它看起来就像我需要的那样。节日快乐!
    【解决方案2】:

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

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

    我相信临时表就足够了。这是一个 asktom,它展示了如何在 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 用户。

    【讨论】:

    • 感谢您的快速回复!我打算在假期结束后重新审视这个问题,看看在我接受任何东西之前我会得到什么其他回答......但到目前为止我喜欢这个。
    • @klay,祝你好运,节日快乐!如果您遇到任何问题,请告诉我结果是什么
    • 感谢您的帮助和链接!也祝你节日快乐!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 2015-11-03
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    相关资源
    最近更新 更多