Повышение производительности рекурсивного CTE - PullRequest
0 голосов
/ 26 мая 2020

У меня есть довольно простой рекурсивный CTE, работающий на одной исходной таблице (REP.INVENTMOVEMENTS), содержащей около 4 миллионов записей. Таблица довольно сильно проиндексирована.

with 
dataset as (
    select imv.sourceBatch, 
           imv.targetBatch,
           imv.sourceDataArea, 
           imv.targetDataArea,
           sum(Weight) as Weight
    from REP.INVENTMOVEMENTS imv 
    where imv.sourceBatch <> ''
    Group By imv.sourceBatch, 
             imv.targetBatch,
             imv.sourceDataArea, 
             imv.targetDataArea
    ),
result as (
    select  targetBatch as Batch,
            targetDataArea as DataArea, 
            sourceBatch, 
            targetBatch,   
            sourceDataArea,
            targetDataArea, 
            1 as level,
            Weight
    from dataset
    where sourceBatch <> targetBatch

    union all 

    select result.Batch,
           result.DataArea, 
           dataset.sourceBatch, 
           dataset.targetBatch, 
           dataset.sourceDataArea,
           dataset.targetDataArea, 
           result.level + 1 as level,
           dataset.Weight
    from dataset inner join result on dataset.targetBatch       = result.sourceBatch 
                                  and dataset.targetDataArea    = result.sourceDataArea
                                  and dataset.targetBatch       <> dataset.sourceBatch
    )

select * from result
union all
select      targetBatch as Batch,
            targetDataArea as DataArea, 
            sourceBatch, 
            targetBatch,   
            sourceDataArea,
            targetDataArea, 
            0 as level,
            Weight
    from dataset
    where sourceBatch = targetBatch
;

выполнение начального запроса без выборки занимает у базы данных 122 секунды, возвращая 517,947 записей.

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

Но если я запустил CTE с выбором для 1 пакета, базе данных потребуется 28 секунд, чтобы завершить 2 рекурсии и вернуть 7 записей.

Мне нужно заполнить таблица с результатом из этого представления для пакетов 150k. поэтому, если все они займут полминуты, потребуется 52 дня, чтобы завершить sh эту задачу.

Это план выполнения

План выполнения

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

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

Пожалуйста, примите во внимание, что одна партия может использоваться в нескольких других партиях.

Надеюсь, вы можете мне помочь.

1 Ответ

0 голосов
/ 26 мая 2020

Я решил проблему, создав внутреннюю таблицу и заполнив ее набором данных, необходимым для выполнения рекурсивного запроса.

DECLARE @BatchSequence as table( Batch          nvarchar(100),
                                 SourceBatch    nvarchar(100),
                                 TargetBatch    nvarchar(100),
                                 Weight         decimal(18,3));

insert into @BatchSequence 
select ReportingBatch, SourceBatch,TargetBatch, SUM(Weight) as Weight
from REP.INVENTMOVEMENTS
WHERE sourceBatch <> ''
Group By ReportingBatch, SourceBatch,TargetBatch;

with 
result as (
    select  targetBatch as Batch,
            sourceBatch, 
            targetBatch,   
            1 as level,
            Weight
    from @BatchSequence dataset
    where sourceBatch <> targetBatch

    union all 

    select result.Batch,
           dataset.sourceBatch, 
           dataset.targetBatch, 
           result.level + 1 as level,
           dataset.Weight
    from @BatchSequence dataset inner join result on dataset.targetBatch        = result.sourceBatch 
                                  and dataset.targetBatch       <> dataset.sourceBatch
    )

Это возвращает 250 тыс. Записей за 1 минуту

Надеюсь на это может помочь кому-то другому.

...