SQL Server: INNER JOIN после UNION приводит к медленному совпадению хэшей (агрегат) - PullRequest
2 голосов
/ 10 декабря 2010

Вот CTE, который замедляет всю хранимую процедуру:

select * 
from #finalResults
where intervalEnd is not null
union
select            
    two.startTime, 
    two.endTime,
    two.intervalEnd,
    one.barcodeID,
    one.id,
    one.pairId,
    one.bookingTypeID,
    one.cardID,
    one.factor,
    two.openIntervals,
    two.factorSumConcurrentJobs
from #finalResults as one
inner join #finalResults as two
    on  two.cardID = one.cardID
    and two.startTime > one.startTime
    and two.startTime < one.intervalEnd

Таблица #finalResults содержит чуть более 600K строк, верхняя часть UNION (where intervalEnd is not null) - около 580K строк,нижняя часть с объединенными #finalResults примерно 300K строк.Тем не менее, это внутреннее объединение оценивается в конечном итоге с колоссальными 100 млн.строки, которые могут быть ответственны за длительное хэш-совпадение здесь: alt text

Теперь, если я правильно понимаю хеш-соединения , меньшая таблица должна быть сначала хеширована, а большая таблица вставленаи если вы сначала догадались, что размеры неправильны, вы получите снижение производительности из-за смены ролей в середине процесса.Может ли это быть причиной медлительности?
Я пытался явно указать inner merge join и inner loop join в надежде улучшить оценку числа строк, но безрезультатно.
Еще одна вещь: Eager Spool в правом нижнем углуоценивает 17K строк, в итоге 300K строк и выполняет почти полмиллиона повторных и перезаписей.Это нормально?

Редактировать: Временная таблица #finalResults содержит индекс:

create nonclustered index "finalResultsIDX_cardID_intervalEnd_startTime__REST"
on #finalresults( "cardID", "intervalEnd", "startTime" )
include( barcodeID, id, pairID, bookingTypeID, factor,
         openIntervals, factorSumConcurrentJobs );

Нужно ли мне также создавать отдельную статистику?

Ответы [ 2 ]

1 голос
/ 10 декабря 2010

Я сталкивался с ситуациями, когда UNION выполнял запрос намного медленнее, чем UNION ALL с последующим DISTINCT. Поэтому, хотя у меня нет объяснения плохому плану запросов (статистика и индексы в порядке?), Я предлагаю вам попробовать следующее:

select distinct * from (
    select * 
    from #finalResults
    where intervalEnd is not null
    union all
    select            
        two.startTime, 
        two.endTime,
        two.intervalEnd,
        one.barcodeID,
        one.id,
        one.pairId,
        one.bookingTypeID,
        one.cardID,
        one.factor,
        two.openIntervals,
        two.factorSumConcurrentJobs
    from #finalResults as one
    inner join #finalResults as two
        on  two.cardID = one.cardID
        and two.startTime > one.startTime
        and two.startTime < one.intervalEnd
)
0 голосов
/ 10 декабря 2010

Возможно, это улучшится, если вы создадите статистику для столбца cardID.

...