Oracle Присоединяйтесь к двум огромным таблицам

У меня есть процедура Oracle, которая состоит из нескольких блоков EXECUTE IMMEDIATE. Один из них - объединить две большие таблицы (~ 100-200 000 000 записей):

 v_sql:='create table idb.cm_contact_add_char_exp_tmp as  
select ch.* from idb.cm_contact_add_char_exp ch  join
idb.communication_contact_exp_tmp cont on  cont.customer_rk=ch.customer_rk and ch.RESPONSE_TRACK_CD=cont.RESPONSE_TRACK_CD'

execute immediate v_sql;

Первая таблица (CH) имеет индекс на (CUSTOMER_RK,RESPONSE_TRACK_CD) и раздел на дату.

SQL_PLAN: введите здесь описание изображения

Оракл выдает следующую ошибку:

Ошибка SQL: ORA-01652: невозможно расширить временный сегмент на 64 в табличном пространстве TEMP


person Jdzel    schedule 19.12.2017    source источник
comment
Я не уверен, что динамический аспект имеет отношение к вопросу. Наверняка у вас была бы такая же проблема без него.   -  person William Robertson    schedule 19.12.2017
comment
Есть ли какой-либо фильтр, который вы можете применить, например, дату раздела, которую вы упомянули? В настоящее время вы присоединяетесь к обеим таблицам целиком (4384 раздела). Предполагая, что данные постоянно растут, если у вас нет какого-либо рутинного процесса очистки, это всегда в конечном итоге достигнет точки, когда они превысят доступные ресурсы.   -  person William Robertson    schedule 19.12.2017
comment
Итак, в чем проблема с динамическими запросами?   -  person Jdzel    schedule 19.12.2017
comment
Это добавляет сложности и скрывает ошибки и зависимости до времени выполнения. Однако с точки зрения вашего mcve это кажется ненужной деталью.   -  person William Robertson    schedule 19.12.2017
comment
Могу ли я исправить ошибку с временным сегментом, если я заменю его на SQL-запрос?   -  person Jdzel    schedule 20.12.2017
comment
Быть динамическим или статическим не влияет на количество используемых ресурсов, если вы об этом спрашиваете.   -  person William Robertson    schedule 20.12.2017
comment
Ок, спасибо, но главный вопрос - как исправить ошибку. Не могли бы вы помочь мне с этим?   -  person Jdzel    schedule 20.12.2017
comment
Вам действительно нужно обрабатывать все разделы 4384 сразу? Можете ли вы сделать это в пакетах? Обычно такие пакеты выполняются только для определенного дня, поэтому я подумал, не пропустили ли вы параметр.   -  person William Robertson    schedule 20.12.2017


Ответы (2)


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

Кстати, почему вы создаете таблицу именно так? Это необычно; вообще говоря, вы должны создавать таблицы на SQL, а не на PL/SQL.

person Littlefoot    schedule 19.12.2017
comment
Вы думаете, что только блоки PL/SQL создают большие временные сегменты? - person Jdzel; 19.12.2017
comment
С чего ты взял, что я так думаю? Я сказал, что ОП не должен СОЗДАВАТЬ ТАБЛИЦУ с помощью PL/SQL; для этого редко бывает веская причина, поэтому я предложил сделать это в SQL. После создания таблицы вставьте в нее данные. Поскольку исходные таблицы содержат огромное количество миллионов строк и разделены, INSERT INTO может выполняться по частям, чтобы табличное пространство TEMP не взорвалось. - person Littlefoot; 19.12.2017

Другая возможность - сначала динамически создать таблицу - если это действительно то, что вам нужно - с помощью

CREATE TABLE idb.cm_contact_add_char_exp_tmp AS
SELECT ch.*
  FROM idb.cm_contact_add_char_exp ch  
 WHERE 1=0

Затем используйте массовые операции FORALL для вставки записей из исходных таблиц.

Я бы спросил, зачем вам нужна временная таблица, содержащая около 200 миллионов строк. Звучит немного подозрительно для меня.

person BriteSponge    schedule 19.12.2017
comment
Вы думаете, что только блоки PL/SQL создают большие временные сегменты? Я полагаю, что основная проблема заключается в большом объединении - person Jdzel; 19.12.2017