2017-02-22 52 views
0

Эта часть запроса делает его довольно плохим, к сожалению, не видно пути, оптимизируйте.Abysmal performance - Hash join берет> 80% стоимости запроса в SQL Server 2012

update #db set contents = i.contents 
from (select distinct 
(select max(ac.contents) from ##dwv d 
left join ##calendar c on 1=1 
left join #db ac on d.id = ac.id 
and c.ReportingPeriod = ac.DateValue and ac.Data_Type = 'ActivePeriod' 
where d.ID = dd.id and month_number >= (cc.month_number-3) 
and month_number <= cc.month_number) contents 
,dd.id 
,cc.ReportingPeriod 
from #db dd 
left join ##calendar cc on cc.ReportingPeriod = dd.DateValue 
where dd.Data_Type = 'ActivePeriod' 
)i 
where i.id = #db.id and i.ReportingPeriod = #dashboard.DateValue 

Я пытался сначала слить его, но не пошел куда-то быстро, и этот щенок появился.

Идея заключается в том, чтобы отметить каждого клиента активным в любой заданный период (год, месяц в формате «YYYYMM») в соответствии с конкретным алгоритмом, поэтому для каждого клиента, который соответствует критериям отчета, мне нужно иметь строку, которая будет скажите мне, был ли он активным (то есть: недавно купил).

#db является временной таблицей, где я собираю все данные, которые будут впоследствии использоваться для агрегатов для получения отчета - большой стола в нескольких миллионов строк, в зависимости от сроков:

Create table #db 
(
    C_P varchar(6) 
    ,Data_Type varchar(20) 
    ,id int 
    ,contents int 
    ,DateValue varchar(10) 
) 

##dwv является температурой таблица, где я сбрасываю результат выбора на большом представлении (который сам очень медленный) занимает около 2,4 млн. строк

##calendar - это специальная таблица, которая хранит каждый период, когда отчет охватывает тот же формат ' ГГГГММ:

select CONVERT(char(6), cast(@startdate as date), 112) "CP" 
     ,CONVERT(char(6), cast(PKDate as date), 112) "RP" 
     ,(ROW_NUMBER() over (order by (CONVERT(char(6), cast(PKDate as date), 112)) asc))-1 
     as month_number 
into ##calendar 
from [calendar].[dbo].[days] 
where PKDate between @startdate and @enddate2 
group by CONVERT(char(6), cast(PKDate as date), 112) 

план запроса говорит мне, что бит c.ReportingPeriod = ac.DateValue является cuplrit - занимает 88% от стоимости подзапросов с ним, что в свою очередь приходится 87% от стоимости всего запроса.

Что я не вижу здесь и как я могу улучшить это?

+0

Добавили ли вы индексы в свои временные таблицы? Вы уверены, что вы должны сбросить все эти данные в временные таблицы вместо того, чтобы использовать существующие таблицы и индексы?Поделитесь своими планами выполнения, используя [Paste The Plan @ brentozar.com] (https://www.brentozar.com/pastetheplan/) – SqlZim

+0

Будьте очень осторожны с использованием глобальных временных таблиц. Там много проблем с параллелизмом. И почему левые соединяются с 1 = 1 как единственный предикат? Разве это не было бы проще в качестве креста? –

+0

Выполняется обновление, основанное на соединении с отдельным в результирующем наборе с выражением столбца, которое использует коррелированный подзапрос с агрегированием в правой таблице левого соединения. Можете ли вы опубликовать определение планов выполнения и всех таблиц и объяснить бизнес-проблему, которую вы пытаетесь решить? Нам может быть несколько сложно разгадать этот запрос. –

ответ

1

Hash Joins обычно означает, что столбцы, используемые в JOIN, не индексируются.

Убедитесь, что покрытие индексов для этих столбцов:

d.id = ac.id и c.ReportingPeriod = ac.DateValue и ac.Data_Type

+0

Я сделал это. Сначала это помогло с успехом, но не надолго, поэтому я задал вопрос. Но этот рецидив произошел из-за того, что я все время сбрасывал код. После того, как у меня была стабильная бета-версия отчета, и ударили индексы во всех используемых временных таблицах. За работой. – AcePL

0

Только в случае, если кто-то спотыкается здесь я Я объясню, что я сделал, чтобы сократить время выполнения от 32 минут до 15 секунд.

Один, как предлагается в комментариях и ответах Tab Alleman Я просмотрел индексы для таблиц, где HASH JOIN показан в плане выполнения. Я также более подробно рассмотрел пункты ON для соединений там и здесь, что привело к меньшему количеству строк.

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

Подводя итог, следует обратить внимание на то, о чем жалуется SQL Server, но, по крайней мере, взглянуть на цифры и попытаться опустить их, когда это возможно. Индексирование - это хорошо, но это не «чудодейственное средство» для всего, что вызывает ваш запрос.

Спасибо всем, кто нашел время, чтобы написать здесь - когда несколько человек говорят подобные вещи, всегда приятно сесть и подумать об этом.