2009-07-09 3 views
0

У меня есть приложение, работающее на моем SQL Server, которое начинает замедляться по конкретной задаче. Я запустил SQL Profiler и заметил, что следующий запрос требует огромного (1-2 минуты) времени. У меня нет доступа к коду для изменения запроса.
Есть ли что-нибудь, что я могу настроить/изменить в базе данных? Таблица PC10000 в приведенном ниже заявлении имеет ок. 119000 записей. У меня также есть план выполнения.Tune Slow SQL Query

SELECT TOP 25 
    zProjectID, zTaskID, zTransactionNumber, zTransactionDate, zUserID, 
    zCostCategoryDDL, zCostCategoryString, zSubCostCategory, zSubCostCategoryString, 
    zDepartmentID, zJournalEntry, zPostingDate, zSalesPostingDate, zPeriodNumber, 
    zTransactionDescription, zBillingDescriptionLine1, zBillingDescriptionLine2, 
    zBillingDescriptionLine3, zBillingDescriptionLine4, zSalesAccountIndex, 
    zSalesAccountString, zDistDocumentTypeDDL, zDistDocumentNumber, zDistSequenceNumber, 
    zSalesDocumentTypeDDL, zSalesDocumentNumber, zSalesLineNumber, zDistHistoryYear, 
    zSeriesDDL, zSourceDoc, zWebSource, zOrigDocumentNumber, zOrigDocumentDate, 
    zOrigID, zOrigName, zExpenseStatusDDL, zApprovalUserIDCost, zAccountIndex, 
    zAccountNumberString, zBillingStatusDDL, zApprovalUserIDBilling, zBillingWorkQty, 
    zBillingWorkAmt, zQty, zQtyBilled, zUnitCost, 
    zUnitPrice, zRevenueAmt, zOriginatingRevenueAmt, zCostAmtEntered, zCostAmt, 
    zOriginatingCostAmt, zPayGroupID, zPayrollStatusDDL, zTotalTimeStatusDDL, 
    zEmployeeID, zHoursEntered, zHoursPaid, zPayRecord, zItemID, zItemDescription, 
    zUofM, zItemQty, zBurdenStatusDDL, zUserDefinedDate, zUserDefinedDate2, 
    zUserDefinedString, zUserDefinedString2, zUserDefinedCurrency, 
    zUserDefinedCurrency2, zNoteIndex, zImportType, DEX_ROW_ID 
FROM 
    DBServer.dbo.pc10000 
WHERE 
    (zDistDocumentNumber in 
     (select cast(JRNENTRY as varchar(20)) 
      from DBServer..GL10001 
      where BACHNUMB = 'PMCHK00004283') 
    or zSalesDocumentNumber in 
     (select cast(JRNENTRY as varchar(20)) 
      from DBServer..GL10001 
      where BACHNUMB = 'PMCHK00004283')) 
ORDER BY 
    zProjectID ASC ,zTaskID ASC ,zTransactionNumber ASC 

alt text

+0

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

+1

Отредактировано, чтобы подчеркнуть тот факт, что он НЕ МОЖЕТ ИЗМЕНИТЬ ЗАПРОС. –

+0

Почему код не может быть отредактирован. Выполняется ли запрос через хранимую процедуру? – pjp

ответ

6

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

Таблица Сканирует производительность, так как это означает, что вся таблица сканируется для данных, соответствующих данным предложениям в запросе.

Я рекомендую вам добавить индекс BACHNUMB в GL10001

Вы также можете попробовать индексы zDistDocumentNumber и zSalesDocumentNumber в PC10000, но я думаю, что индекс GL10001 является основным.

Предложения "IN" обычно довольно дороги по сравнению с другими методами, но поскольку вы не можете изменить сам запрос, то вы ничего не можете с этим поделать.

Без сомнения, вам нужно добавить соответствующие индексы

3

Запрос делает сканирование таблицы 2 на столе GL10001. Из быстрого просмотра запроса (который немного трудно читать) я бы увидел, есть ли указатель в столбце BACHNUMB.

+1

Поскольку эти два подзапроса каждый берут (согласно плану выполнения) 47% от общего времени, черт возьми, индексируйте их. Насколько велика таблица GL10001? –

0

Вы можете переписать эти суб-выбирает в качестве соединения, и добавить индекс GP01..GL10001 на BACHNUMB и JRNENTRY

+1

К сожалению, он упоминает, что он не может изменить запрос. –

+0

@Justin Niessner: добавление индекса не изменяет запрос. Если он хочет получить максимальную выгоду, тогда эти подзаголовки должны быть объединены –

0

Поскольку вы не можете изменить запрос, то лучшее, что вы можете сделать, это убедиться, у вас есть индексы столбцов, которые вы используете для своих объединений (и подзапросов). Если вы можете подумать о лучшем плане запроса, вы можете предоставить это SQL Server вместо того, чтобы позволить ему вычислить его собственный (это очень редкий случай).

1

план выполнения показывает довольно ясно, что на самом деле размещение строк является то, что берет все время (отсутствие громоздких закладки Lookups или агрегацию/переставить задачи), так что вполне положительно будет вопрос индексации. наведите указатель на таблицу в план выполнения и проверьте «объект» в подсказке, чтобы увидеть, какие столбцы используются. следить за тем, чтобы они были проиндексированы.

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

0

Заменить ИЛИ с UNION ALL из двух запросов это должно получить выстрел из этих катушек

т.е. выполнить запрос один раз что-то вроде этого

SELECT .... 

(zDistDocumentNumber in 
    (select cast(JRNENTRY as varchar(20)) 
     from DBServer..GL10001 
     where BACHNUMB = 'PMCHK00004283') 

UNION ALL 

SELECT ... 

zSalesDocumentNumber in 
    (select cast(JRNENTRY as varchar(20)) 
     from DBServer..GL10001 
     where BACHNUMB = 'PMCHK00004283')) 
+0

ypu избили меня! Я согласен с pjp ... также добавляю индексы. –

+0

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

0

В дополнении к добавлению индексов , вы также можете конвертировать инструкции IN в EXISTS ...что-то в этих строках:

SELECT TOP 25 .... 
FROM GP01.dbo.pc10000 parent 
WHERE EXISTS 
    (
    SELECT child.* 
    FROM GP01..GL10001 child 
    WHERE BACHNUMB = 'PMCHK00004283' 
     and parent.zDistDocumentNumber = child.JRNENTRY 
    ) 
    OR EXISTS 
    (
    SELECT child2.* 
    FROM GP01..GL10001 child2 
    WHERE BACHNUMB = 'PMCHK00004283' 
     and parent.zSalesDocumentnumber = child2.JRENTRY 
    ) 
ORDER BY zProjectID ASC ,zTaskID ASC ,zTransactionNumber ASC