Получать данные из памяти вместо таблицы

У меня есть таблица параметров с 10 строками. Вызывается параметрическая таблица. В моей процедуре PL/SQL я делаю цикл в 2 миллиона записей. И каждый раз запрашивая эту таблицу параметров тоже.

Я хочу загрузить эту таблицу параметров в память и уменьшить процесс ввода-вывода.

Каков наилучший способ сделать это?

 FOR cur_opt
  IN (SELECT customer_ID,
             NVL (customer_type, 'C') cus_type
        FROM invoice_codes 
       WHERE ms.invoice_type='RT') 
LOOP
  ....
  ...

  Select data From parameter_table Where cus_type = cur_opt.cus_type AND cr_date < sysdate ;  -- Where clause is much complex than this..

....
...
END LOOP;

3 ответа

Вы можете просто присоединить его к своему основному запросу:

select customer_id, data
from   parameter_table t, invoice_codes c
where  t.cus_type = nvl(c.customer_type, 'C')
and    t.cr_date < sysdate

Однако, если у вас есть 2 миллиона записей в invoice_codesзатем присоединение к таблице параметров - это наименьшая из ваших проблем - циклическое выполнение этого займет некоторое время (и, вероятно, является реальной причиной ваших проблем ввода-вывода).

Я думаю, что вы можете изменить запрос, присоединившись к параметру-таблице, так что вам не нужно будет нажимать оператор выбора внутри цикла. (например, какое решение @Chris Saxon)

Но в качестве способа использования кэшированных данных вы можете заполнить словарь, например, массив, а затем ссылаться на него при необходимости.
Нечто подобное может помочь:

ты должен позвонить Fill_parameters_cash перед началом основного процесса и вызова get_parameter чтобы получить данные, входной параметр для вызова get_parameter это словарь ключ

TYPE ga_parameter_t IS TABLE OF parameter_table%ROWTYPE INDEX BY BINARY_INTEGER;
ga_parameter ga_parameter_t;

procedure Fill_parameters_cash is
  begin 
    ga_parameter.DELETE;
    SELECT * BULK COLLECT
    INTO   ga_parameter
    FROM   parameter_table;    
end Fill_parameters_cash;

FUNCTION get_parameter(cus_type invoice_codes.cus_type%TYPE,
                                 is_fdound    OUT BOOLEAN)
    RETURN parameter_table%ROWTYPE IS
    result_value parameter_table%ROWTYPE;

    pos NUMBER;
  BEGIN
    result_value := NULL;
    is_fdound := FALSE;
    IF cus_type IS NULL THEN
      RETURN NULL;
    END IF;  

    pos := ga_parameter.FIRST;
    WHILE pos IS NOT NULL
    LOOP
      EXIT WHEN ga_parameter(pos).cus_type  = cus_type;
      pos := ga_parameter.NEXT(pos);
    END LOOP; 
   IF pos IS NOT NULL THEN
      is_fdound    := TRUE;
      result_value := ga_parameter(pos);
    END IF;  
    RETURN result_value;
  END get_parameter; 

Я предполагаю, что просмотр миллионов записей уже вызывает проблемы. Не совсем уверен, как этот поиск таблицы параметров действительно ухудшает его.

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

----
 FOR cur_opt
  IN (SELECT customer_ID,
             NVL (customer_type, 'C') cus_type
        FROM invoice_codes codes,
             parameter_table par 
       WHERE ms.invoice_type='RT'
         and codes.cus_type = par.cus_type -- (or an outer join) maybe?
      ) loop
..........
Другие вопросы по тегам