Те же вопросы, разные серверы, разные планы EXEC, статистика обновлена
-
16-10-2019 - |
Вопрос
У меня есть один и тот же запрос, запускающийся на двух разных серверах, и я получил совершенно разные выступления. Я обновил все статистики на зависимых объектах, и это не исправило проблему. Я потерян, куда обратиться в дальнейшее.
Вот как выглядят планы, то верхний исполнение Dex (то, что работает), и дно является выполнением теста (медленное).
РЕДАКТИРОВАТЬ: Вот как выглядит SQL:
ALTER procedure [ardb].[NewProjects]
-- Add the parameters for the stored procedure here
as
begin
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
set NOCOUNT on ;
-- Insert statements for procedure here
;with b as
(
select distinct
coalesce(a.STUDY_NUMBER,b.STUDY_NUMBER, c.study_number) as StudyNumber
from
(
SELECT SUBSTRING(PAPROJNUMBER, 1, 5) AS STUDY_NUMBER
FROM appdb.PROD.dbo.PA01201 AS PA01201_1
where PAPROJNUMBER>'0'
and PAPROJNUMBER not like '%[a-z]%'
) a
full outer join
(
SELECT SUBSTRING(PAPROJNUMBER, 1, 5) AS STUDY_NUMBER
FROM appdb.MO1.dbo.PA01201 AS PA01201_1
where PAPROJNUMBER>'0'
and PAPROJNUMBER not like '%[a-z]%'
) b
on a.STUDY_NUMBER=b.STUDY_NUMBER
full outer join
(
SELECT STUDY_NUMBER
FROM appdb.ptwdb.dbo.tblARCompletedStudies
where STUDY_NUMBER>'0'
) c
on a.STUDY_NUMBER=c.study_number
and b.STUDY_NUMBER=c.study_number
)
select
snStudyNumber as ProjectNumber,
c.clName as CompanyName,
q.quQuoteNumber as QuoteNumber,
q.quQuoteID as QuoteID,
q.quDateWon as DateWon,
s.snPTWCompletionDate as PTWCompletionDate
from CDB.cdb.Quotes q
inner join CDB.cdb.LineItems l
on q.PK_quID=l.FK_quID
inner join CDB.cdb.StudyNumbers s
on l.FK_snID=s.PK_snId
inner join cdb.cdb.Clients c
on q.FK_clID=c.PK_clID
left outer join ardb.projects p
on s.snStudyNumber=p.prProjectNumber
left outer join b
on s.snStudyNumber=b.studynumber
where q.quDateWon>''
and s.snPTWCompletionDate >''
and p.PK_prID is null
and l.liCreationDate>'12/31/06'
and b.studynumber is null
union all
select CAST(ProjectNumber AS int) as ProjectNumber,
null as CompanyName,
null as QuoteNumber,
null as QuoteID,
null as DateWon,
null as PTWCompletionDate
from history.ProjectsToProcess a
left outer join ardb.projects p
on a.ProjectNumber=p.prProjectNumber
where p.PK_prID is null
order by ProjectNumber desc
end
XML планы: здесь
Решение
В медленном плане подпродир плана, содержащий все удаленные запросы, выполняется 2928 раз. Это было бы 3632 раза (количество строк на внешнем входе в вложенное соединение петлей, которое имеет подторие удаленного запроса на своей внутренней стороне), но отчетливый сортирует (повторно используется) результаты предыдущей итерации на Несколько случаев.
В быстром плане соединение является хэш-соединением, а не вложенными петлями, поэтому проблематичное подрисование выполняется только один раз. Как обычно, причиной, вероятно, являются небольшие различия в оценке кардинальности (видимых в плане как оценочное количество строк) и полученные гистограммы и статистику распределения (не столь заметны). Этот вариант, вероятно, связан с немного разными образцами, взятыми для построения статистики, или статистики, построенной в разное время между Dev и Test.
Чтобы быстро подтвердить это, вы можете добавить OPTION (HASH JOIN)
к запросу. Существует небольшой риск, что оптимизатор будет жаловаться, что он не может составить план с этим намеком. Я не проанализировал план достаточно глубоко, чтобы предсказать это, и это предложение предназначено только для демонстрационных целей. Это не мое предложенное решение.
Лучшее исправление - разбить запрос на секции. Refactor Обработка подрисков отдаленного запроса в отдельный запрос и храните строки 6737, которые он производит во временной таблице. Вы, вероятно, захотите использовать таблицу #Temporary, а не переменную таблицы, поскольку вы получите автоматическую статистику, и у вас будет более широкий диапазон возможностей индексации, если это окажется полезным.
Запросы со многими объединениями и удаленными запросами имеют очень большое количество возможных договоренностей. Разумно разумно пробивая запрос и предоставляя статистику (и, возможно, индексы), вы предоставляете оптимизатор лучшую информацию и меньшее пространство поиска для изучения. Ваши шансы на хороший план растут.
Другие советы
Похоже, ваша проблема может быть с Удаленный запрос Operators ShowPlan. Они самые дорогие, привязанные к 38.9% а также 14.5% Для медленных запросов. Можете ли вы дать нам немного больше информации относительно источника этих запросов и выполнения, основанного на них?
Запустите трассировку с SQL Profiler, чтобы увидеть, где самая продолжительность продолжительности находится на медленном запросе, и сравните их с более быстрым запросом. Вы сможете точно определить операторы/процедуры, которые являются самыми дорогими, и это сузится ваши устранения неполадок.