Truecolors Ответов: 1

Как повысить производительность 10-минутного запроса?


У меня есть запрос, который занимает примерно 10 минут, чтобы выполнить и получить результаты. Когда я пытаюсь разбить его на части и запустить, он, кажется, работает нормально, в течение нескольких секунд.

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

Затем я прогнал нижнюю часть отдельно,
join(select glP.fkosControlNumberStatus....


И он побежал в течение 1 секунды.

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

Кто-нибудь может помочь мне в улучшении производительности этого запроса, пожалуйста?

Что я уже пробовал:

Set Nocount On
Declare @YearEndDate DateTime = '2016-12-31'
set @YearEndDate = dbo.fnGetDatePartOnly(@YearEndDate)

Select Distinct
       glPostExtended.BatchNumber,
       postData.fkosControlNumberStatus,
       postData.AccountSegment Fund,
       postdata.Debit,
       postData.Credit,
       postdata.DistAmountTotal,
       glPostExtended.SubLedger Module,
       glPost.SourceJENumber,
       glPost.PostToDate
From
       glPost WITH (NOLOCK)
       --This joins limits the glPostExtended Records from duplicating glPost Records for Summarized posting
    join (Select fkglPost, MAX(fkglDist) as fkglDist, COUNT(fkglDist) as RecordCount From glPostExtended WITH (NOLOCK) Group By fkglPost) as glPostExtendedLimiter on glPost.PK = glPostExtendedLimiter.fkglPost
    join glPostExtended WITH (NOLOCK) on glPostExtendedLimiter.fkglPost = glPostExtended.fkglPost and (glPostExtendedLimiter.fkglDist = glPostExtended.fkglDist or glPostExtended.fkglDist is null)
       join (select glP.fkosControlNumberStatus, glP.SourceJENumber, AccountSegment, 
                 sum(case 
                       when glP.DistAmount > 0 then glP.DistAmount
                       else 0
                 end) Debit,
                 sum(case
                       when glP.DistAmount < 0 then glP.DistAmount
                       else 0
                 end) Credit,
                 sum(glP.DistAmount) DistAmountTotal
                from glPost glP WITH (NOLOCK)
                  join glAccountingPeriod WITH (NOLOCK) on glAccountingPeriod.pk = glP.fkglAccountingPeriod
                  join glFiscalYear WITH (NOLOCK) on glFiscalYear.pk = glAccountingPeriod.fkglFiscalYear
                  join glAccount WITH (NOLOCK) on glAccount.pk = glFiscalYear.fkglAccount
                where dbo.fnGetDatePartOnly(glFiscalYear.PeriodEnd) = @YearEndDate
                 and glP.fkMLSosCodeEntryType = 2202
                group by glP.fkosControlNumberStatus, glP.SourceJENumber, AccountSegment) postdata on postdata.fkosControlNumberStatus = glPost.fkosControlNumberStatus and postdata.SourceJENumber = glPost.SourceJENumber
where postdata.DistAmountTotal <> 0
  and glPost.fkMLSosCodeEntryType = 2202
order by glPostExtended.BatchNumber, glPost.SourceJENumber, postData.AccountSegment



Попробовал изменить верхнюю часть подселективного соединения Вот так, и это не заняло слишком много времени

Select Distinct
	glPostExtended.BatchNumber,
	--postData.fkosControlNumberStatus,
	--postData.AccountSegment Fund,
	--postdata.Debit,
	--postData.Credit,
	--postdata.DistAmountTotal,
	glPostExtended.SubLedger Module,
	glPost.SourceJENumber,
	glPost.PostToDate
From
	(Select fkglPost, MAX(fkglDist) as fkglDist, COUNT(fkglDist) as RecordCount From glPostExtended WITH (NOLOCK) Group By fkglPost) as glPostExtendedLimiter
	join glPostExtended WITH (NOLOCK) on glPostExtendedLimiter.fkglPost = glPostExtended.fkglPost and (glPostExtendedLimiter.fkglDist = glPostExtended.fkglDist or glPostExtended.fkglDist is null)
	 inner join glPost WITH (NOLOCK) 
		on glPostExtendedLimiter.fkglPost = glPost.PK 

ZurdoDev

Вам нужно обратиться к плану выполнения. Мы никак не можем знать, что заставляет его тянуться так долго.

RickZeeland

Однажды у меня была такая загадочная проблема,как перестройка / реорганизация индексов.
Видишь http://www.sql-server-performance.com/2007/rebuilding-indexes/

1 Ответов

Рейтинг:
8

CHill60

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

С точки зрения понимания плана выполнения вы можете найти эту статью CodeProject полезной: Учебник по настройке SQL-понимание плана выполнения базы данных (1)[^]

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

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

Что-то вроде этого:

select glP.fkosControlNumberStatus, glP.SourceJENumber, AccountSegment, 
        sum(case when glP.DistAmount > 0 then glP.DistAmount else 0 end) Debit,
        sum(case when glP.DistAmount < 0 then glP.DistAmount else 0 end) Credit,
        sum(glP.DistAmount) DistAmountTotal
INTO #postdata 
from glPost glP WITH (NOLOCK)
join glAccountingPeriod WITH (NOLOCK) on glAccountingPeriod.pk = glP.fkglAccountingPeriod
join glFiscalYear WITH (NOLOCK) on glFiscalYear.pk = glAccountingPeriod.fkglFiscalYear
join glAccount WITH (NOLOCK) on glAccount.pk = glFiscalYear.fkglAccount
where dbo.fnGetDatePartOnly(glFiscalYear.PeriodEnd) = @YearEndDate
and glP.fkMLSosCodeEntryType = 2202
group by glP.fkosControlNumberStatus, glP.SourceJENumber, AccountSegment
затем
Select Distinct
       glPostExtended.BatchNumber,
       pd.fkosControlNumberStatus,
       pd.AccountSegment Fund,
       pd.Debit,
       pd.Credit,
       pd.DistAmountTotal,
       glPostExtended.SubLedger Module,
       glPost.SourceJENumber,
       glPost.PostToDate
From
       glPost WITH (NOLOCK)
       --This joins limits the glPostExtended Records from duplicating glPost Records for Summarized posting
    join (Select fkglPost, MAX(fkglDist) as fkglDist, COUNT(fkglDist) as RecordCount From glPostExtended WITH (NOLOCK) Group By fkglPost) as glPostExtendedLimiter on glPost.PK = glPostExtendedLimiter.fkglPost
    join #postdata pd on pd.fkosControlNumberStatus = glPost.fkosControlNumberStatus and pd.SourceJENumber = glPost.SourceJENumber
where pd.DistAmountTotal <> 0
  and glPost.fkMLSosCodeEntryType = 2202
order by glPostExtended.BatchNumber, glPost.SourceJENumber, pd.AccountSegment
Во всяком случае, будет легче интерпретировать план исполнения!


0x01AA

- Во всяком случае, будет легче интерпретировать план исполнения!":
Который (План исполнения) очень часто нелегко интерпретировать :)
А 5 за всю информацию

CHill60

Иногда я смотрю на план выполнения и восклицаю: "wtf?!" :)
Спасибо за 5

[no name]

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

[no name]

У меня есть вопрос. Когда вы сделали

INTO #postdata
, именно там вы создали временную таблицу postdata? Я ищу то, что есть в sql, так как я никогда не знал об этом раньше.

CHill60

Да-таким образом вы можете создавать временные таблицы из SELECT. Вам не нужно сначала создавать или объявлять его. Если таблица уже существует, вы можете использовать INSERT INTO #postdata (..columns..) Выберите ... и т. д. Мне действительно следовало сначала удалить его, если это был повторный запуск-см. sql-удаление временной таблицы, если она существует - переполнение стека[^]
Я также только что заметил ошибку в своем запросе where postdata.DistAmountTotal <> 0 должно быть where pd.DistAmountTotal <> 0- Сейчас я это исправлю.

[no name]

Я исправил эту часть, Спасибо. Единственное, что я получаю, это проблема с Скрыть   скопировать код

glPostExtended.SubLedger Module
. Это говорит о том, что многосоставный идентификатор glPostExtended... не может быть найден.

EDIT: ничего страшного, я добавил соединение, которое отсутствовало в оригинале. Когда я запускаю его снова, я получаю ошибку, о которой вы говорили: "в базе данных уже есть объект с именем" #postdata".