Как эффективно подготовить таблицу сопоставления с большими данными, используя Java - PullRequest
0 голосов
/ 06 августа 2020

Рассмотрим сценарий, в котором у меня есть две таблицы, TABLE_A и TABLE_B. Я хочу создать третью таблицу TABLE_C, которая представляет собой просто таблицу сопоставления, содержащую два столбца, первичный ключ TABLE_A и TABLE_B. TABLE_A и TABLE_B содержат 80 миллионов и 150 миллионов записей соответственно. В настоящее время я написал одну хранимую процедуру в DB2 (это моя БД), которая сначала соединится и выберет записи из обеих таблиц и будет выполнять итерацию с помощью курсора. Во время этой итерации я вставляю в третью таблицу и делаю промежуточную фиксацию.

Теперь эта хранимая процедура выполняется долгое время (около 5 часов), чтобы завершить это, поскольку многострочная вставка невозможна в хранимой процедуре DB2 ( Вот что я понял). Можно ли переместить это в Java, получив записи один раз и вставив из Java с помощью JDB C Batch, чтобы вставка работала в многострочном режиме. Но как сохранить такой большой набор результатов в Java, не получив OutOfMemoryError

Может ли кто-нибудь предложить лучший подход.

ОБНОВЛЕНО:

DECLARE GLOBAL TEMPORARY TABLE  SESSION.TABLE_DGTT AS (
    select a.type_id as type_id,
            a.a_id as a_id,
           b.b_id as b_id
    from TABLE_A a
    inner join TABLE_B b on
    AND b.process_date = i_order_date
    AND b.tgt_date = CASE WHEN 
             a.tgt_date < i_order_date 
             THEN i_order_date ELSE a.tgt_date END
    where not exists ( select 1 from TABLE_C c where 
    a.type_id = c.type_id
    AND a.a_id = c.a_id) 
    AND a.process_date <= i_order_date  
    )                                      
    WITH NO DATA NOT LOGGED ON COMMIT PRESERVE ROWS ;  
    
    DECLARE C1 CURSOR FOR SELECT * FROM SESSION.TABLE_DGTT;
    
    LOAD FROM C1 OF CURSOR INSERT INTO TABLE_C NONRECOVERABLE;

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

Стоит попробовать команду LOAD с использованием процедуры ADMIN_CMD с использованием курсора на основе оператора SELECT с использованием исходных таблиц. Подходит для больших объемов данных. Используйте опцию NONRECOVERABLE, если вы не знакомы с утилитой LOAD. И лучше прочитать о параметрах ЗАГРУЗКИ, чтобы понять побочные эффекты.

0 голосов
/ 06 августа 2020

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

Рассмотрите возможность изменения вашей хранимой процедуры, чтобы использовать подход, основанный на наборах.

Если одного запроса (соединение нескольких таблиц) достаточно, чтобы указать окончательный результирующий набор (для вашего table_C вам не нужны промежуточные таблицы, и вы можете рассмотреть либо с использованием незарегистрированной загрузки для заполнения итоговой таблицы (см. Ниже) или простая записанная в журнал вставка.

Если для обработки требуется одна или несколько промежуточных таблиц для создания окончательного набора результатов, одним из вариантов является создание одного или нескольких not logged DGTT (объявление глобальной временной таблицы) в хранимой процедуре , структура которого соответствует итоговой таблице (TABLE_ C в вашем вопросе). Вы можете использовать on commit preserve rows для DGTT, если для его заполнения необходимо несколько единиц работы (например, несколько insert, update, delete , merge операторы необходимы).

Затем заполните эту таблицу сеанса, используя SQL, избегая построчной обработки (не используйте курсоры для заполнения DGTT используйте обработку множеств, например insert into session.xxxx (...) select... или merge et c. ). Вы можете использовать столько операторов, сколько необходимо для заполнения сеансовой таблицы и фиксации, сколько необходимо для снятия любых блокировок.

Сжать DGTT, если это необходимо. Разделите DGTT (ha sh), если это необходимо. Динамически индексируйте DGTT, если это необходимо, и запускайте его. Все это возможно внутри хранимой процедуры.

Когда вы убедитесь, что содержимое DGTT верное, вы готовы заполнить итоговую таблицу.

Помните, вам нужен только DGTT, если вы действительно необходимо этап набор результатов или выполнить дополнительную обработку или проверки перед записью окончательной таблицы (table_ c) в вашем примере.

Чтобы заполнить окончательную таблицу (либо из исходного источника таблицы с одним объединением нескольких таблиц или из DGTT, на котором вы выполнили любую требуемую обработку), вы можете либо использовать команду unlogged load через хранимую процедуру ADMIN_CMD (если ваш Db2 -серверная платформа поддерживает эту функцию), или вы можете использовать (гораздо медленнее) INSERT INTO TABLE_C(...) SELECT ... FROM... . С записанной вставкой, в зависимости от доступной емкости ваших журналов транзакций, вам может потребоваться выполнить этот шаг в пакетном режиме.

Чтобы использовать load (через admin_cmd () ), необходимо тщательно продумать и планирования, и требует понимания проблем и вовлеченных компромиссов, поэтому внимательно изучите документацию или привлеките для работы опытного программиста.

Это решение требует навыков программирования, компетентности и опыта.

...