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

发布于 2024-10-04 09:36:22 字数 612 浏览 1 评论 0原文

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

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

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

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

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

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

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

I have a Silverlight app that makes multiple (often concurrent) asynchronous calls to an Oracle database. The largest database table stores around 5 million records. Below is a summary of how the Silverlight app works, followed by my question.

  1. The user sets query criteria to select a particular group of records, usually 500 to 5000 records in a group.

  2. An asynchronous WCF call is made to the database to retrieve the values in four fields (latitude, longitude, heading, and time offset) over the selected group of records (meaning the call returns anywhere from 2k to 20k floating point numbers. These values are used to plot points on a map in the browser.

  3. From here, the user can choose to graph the values in one or more of an additional twenty or so fields associated with the initial group of records. The user clicks on a field name, and another async WCF call is made to retrieve the field values.

My question is this: does it make sense in this case to store the records selected in step one in a temp table (or materialized view) in order to speed up and simplify the data access in step three?

If so, can anyone give me a hint regarding a good way to maintain the browser-to-temp-table link for a user's session?

Right now, I am just re-querying the 5 million points each time the user selects a new field to graph--which works until the user selects three or more fields at once. This causes the async calls to timeout before they can return.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

追我者格杀勿论 2024-10-11 09:36:22

我们可以使用 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>

有 3 种方法可以设置、获取和取消设置命名空间。请注意,我们可以使用一个命名空间来保存不同的变量。我只是使用这个包在 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>

此语句用二十个随机行填充临时表:

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. 同样重要,在断开连接的代码中找到一个钩子,该钩子可以在用户每次离开会话时取消设置上下文

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

We can do this using a CONTEXT. This is a namespace in session memory which we can use to store values. Oracle comes with a default namespace, 'USERENV', but we can define our own. The context has to be created by a user with the CREATE ANY CONTEXT privilege; this is usually a DBA. The statement references a PACKAGE which sets and gets values in the namespace, but this package does not have to exist in order for the statement to succeed:

SQL> create context user_ctx using apc.ctx_pkg
  2  /

Context created.

SQL>

Now let's create the package:

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>

There are three methods, to set, get and unset a value in the namespace. Note that we can use one namespace to hold different valiables. I am just using this package to set one variable (USER_ID) in the USER_CTX namespace.

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>

So, how does this solve anything? Here is a table for the temporary storage of data. I'm going to add a column which will hold a token to identify the user. When we populate the table the value for this column will be provided by 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>

... and over that table I create a view:...

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

Now, when I want to store some data in the table I need to set the context with a value with uniquely identifies my user.

SQL> exec ctx_pkg.set_user_id('APC')

PL/SQL procedure successfully completed.

SQL>

This statement populates the temporary table with twenty random rows:

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>

I can retrieve those rows by querying the view. But when I change my USER_ID and run the same query I cannot see them any more:

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>

So, the challenges are:

  1. to establish a token which you can use automatically to uniquely identify a user
  2. to find a hook in your connecting code which can set the context each time the user gets a session
  3. just as importantly, to find a hook in your dis-connecting code which can unset the context each time the user leaves a session

Also, remember to clear out the table once the user has finished with it.

潜移默化 2024-10-11 09:36:22

当我第一次读到这篇文章时,我想到了“全局临时表”(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 用户。

when I first read this I thought 'global temporary table' (gtt) and realized that would not help you in the slightest! This is because the data in a GTT is visible only in a session, and with a stateless web app, probably using connection pooling, there is no guaranteed relationship between application user and database session (one user might be handed different sessions on successive connections, one session will be handed to several different users). Now a temp table should do the trick.

It seems that on each iterative hit, the person (via silverlight) is polling the same data (and a large amount to boot).

I do believe that a temp table would suffice. Here is an asktom that shows how to do this in a web environment. Keep in mind the moment the data is stored it is aging and possibly stale and there will need to be a cleanup job.
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:76812348057

Now to tie it back to the user, not 100% sure how to do this in Silverlight (assuming via asp.net?) is the user authenticated prior to proceding? if so, you ought to be able to take their credentials and utilize that as the source to query against (utilize their user name and/or SID as their primary key and foreign key it against the data table as described in the asktom link).
http://www.codeproject.com/KB/silverlight/SL3WindowsIdentityName.aspx
this links appears to show how to get the current silverlight user in a window's authenticated scheme.

hth

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文