Использование временной таблицы Oracle для нескольких асинхронных HTTP-вызовов - PullRequest
1 голос
/ 24 ноября 2010

У меня есть приложение Silverlight, которое выполняет несколько (часто одновременных) асинхронных вызовов базы данных Oracle.В самой большой таблице базы данных хранится около 5 миллионов записей.Ниже приведена сводная информация о том, как работает приложение Silverlight, и мой вопрос.

  1. Пользователь устанавливает критерии запроса для выбора конкретной группы записей, обычно от 500 до 5000 записей в группе.

  2. В базу данных выполняется асинхронный вызов WCF для извлечения значений в четырех полях (широта, долгота, заголовок и смещение времени) по выбранной группе записей (то есть вызов возвращаетсягде угодно от 2k до 20k чисел с плавающей запятой. Эти значения используются для отображения точек на карте в браузере.

  3. Отсюда пользователь может выбрать отображение значений в одном или несколькихиз дополнительных примерно двадцати полей, связанных с начальной группой записей. Пользователь нажимает на имя поля, и для получения значений поля выполняется еще один асинхронный вызов WCF.

Мой вопрос таков: имеет ли смысл в этом случае сохранять записи, выбранные на первом этапе, во временной таблице (или материализованном представлении), чтобы ускоритьи упростить доступ к данным на третьем шаге?

Если да, может ли кто-нибудь дать мне подсказку относительно хорошего способа сохранить ссылку на браузер на временную таблицу для сеанса пользователя?

Прямо сейчас я просто запрашиваю 5 миллионов точек каждый раз, когда пользователь выбирает новое поле для графика - это работает до тех пор, пока пользователь не выберет три или более полей одновременно.Это вызывает тайм-аут асинхронных вызовов, прежде чем они смогут вернуться.

Ответы [ 2 ]

1 голос
/ 25 ноября 2010

Мы можем сделать это, используя КОНТЕКСТ .Это пространство имен в памяти сеанса, которое мы можем использовать для хранения значений.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_ID) в пространстве имен USER_CTX.

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. , что не менее важно, чтобы найти хук вВаш код отключения, который может сбрасывать контекст каждый раз, когда пользователь покидает сеанс

Кроме того, не забудьте очистить таблицу, как только пользователь закончит с ней.

1 голос
/ 24 ноября 2010

Когда я впервые прочитал это, я подумал «глобальная временная таблица» (gtt) и понял, что это не поможет вам ни в малейшей степени!Это связано с тем, что данные в GTT видны только в сеансе, а в веб-приложении без сохранения состояния, возможно, с использованием пула соединений, нет гарантированной взаимосвязи между пользователем приложения и сеансом базы данных (одному пользователю могут передаваться разные сеансы при последовательных соединенияходин сеанс будет передан нескольким различным пользователям).Теперь временная таблица должна сделать свое дело.

Кажется, что при каждом итеративном попадании человек (через silverlight) опрашивает одни и те же данные (и большое количество для загрузки).

Я верю, что временной таблицы будет достаточно.Вот вопрос, который показывает, как это сделать в веб-среде.Имейте в виду, что в тот момент, когда данные хранятся, они стареют и, возможно, устаревают, и потребуется очистка.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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...