调整慢速SQL查询

时间:2009-07-09 14:36:35

标签: sql-server sql-server-2000

我的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 个答案:

答案 0 :(得分:6)

您遇到的最大问题是缺乏合适的索引。 您可以看到,因为执行计划中存在表扫描。

表扫描性能,因为它们意味着正在扫描整个表以查找与查询中的给定子句匹配的数据。

我建议你在GL10001的BACHNUMB上添加一个索引

您可能还想在PC10000中尝试zDistDocumentNumber和zSalesDocumentNumber上的索引,但我认为GL10001索引是主要索引。

与其他技术相比,“IN”子句通常非常昂贵,但由于您无法更改查询本身,因此无法对此进行任何操作。

毫无疑问,您需要添加合适的索引

答案 1 :(得分:3)

查询在GL10001表上进行了2次表扫描。从快速查看查询(有点难以阅读),我会看到你是否有BACHNUMB列的索引。

答案 2 :(得分:1)

执行计划非常清楚地表明,实际定位行是一直在进行的(没有繁琐的书签查找或聚合/重新排列任务),所以这是一个非常积极的索引问题。将表扫描悬停在执行计划中,并在工具提示中检查“对象”,以查看正在使用的列。确保他们被编入索引。

您可能还希望运行跟踪来对一些实时数据进行采样,并将其提供给数据库优化顾问。

答案 3 :(得分:0)

您可以将这些子选择重写为连接,并在BACHNUMB和JRNENTRY上向GP01..GL10001添加索引

答案 4 :(得分:0)

由于您无法更改查询,因此您可以做的最好的事情是确保您在连接(和子查询)上使用的列上有索引。如果您能想到更好的查询计划,可以将其提供给SQL Server,而不是让它自己计算(这是一种非常罕见的情况)。

答案 5 :(得分:0)

OR 替换为两个查询的 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')) 

答案 6 :(得分: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