Настройте медленный SQL-запрос - PullRequest
0 голосов
/ 09 июля 2009

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

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

Ответы [ 7 ]

6 голосов
/ 09 июля 2009

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

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

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

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

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

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

3 голосов
/ 09 июля 2009

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

1 голос
/ 09 июля 2009

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

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

0 голосов
/ 09 июля 2009

В дополнение к добавлению индексов вы также можете преобразовать операторы 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
0 голосов
/ 09 июля 2009

Замените ИЛИ на СОЮЗ ВСЕХ из двух запросов, которые должны выстрелить из этих катушек

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

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 голосов
/ 09 июля 2009

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

0 голосов
/ 09 июля 2009

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

...