Те же вопросы, разные серверы, разные планы EXEC, статистика обновлена

dba.stackexchange https://dba.stackexchange.com/questions/9234

  •  16-10-2019
  •  | 
  •  

Вопрос

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

Вот как выглядят планы, то верхний исполнение Dex (то, что работает), и дно является выполнением теста (медленное).

Exec Plan

РЕДАКТИРОВАТЬ: Вот как выглядит 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, чтобы увидеть, где самая продолжительность продолжительности находится на медленном запросе, и сравните их с более быстрым запросом. Вы сможете точно определить операторы/процедуры, которые являются самыми дорогими, и это сузится ваши устранения неполадок.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top