调优慢 SQL 查询

发布于 2024-07-27 03:16:16 字数 2179 浏览 5 评论 0原文

我的 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

I got an app running on my SQL Server that is starting to slow down on a specific task. I ran SQL Profiler and noticed that the
following query is taking an enormous (1-2 minutes) amount of time. I don't have access to the code to change the query.
Is there anything I can tune/change in the database? The PC10000 table in the statement below has approx. 119000 records. I also have the execution plan attached.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

七堇年 2024-08-03 03:16:16

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

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

我建议您在 GL10001 中的 BACHNUMB 上添加索引

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

与其他技术相比,“IN”子句通常相当昂贵,但由于您无法更改查询本身,因此您对此无能为力。

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

The biggest problem you have looks to be due to lack of suitable indexes.
You can see that because of the presence of Table Scans within the execution plan.

Table Scans hit performance as they mean the whole table is being scanned for data that matches the given clauses in the query.

I'd recommend you add an index on BACHNUMB in GL10001

You may also want to try indexes on zDistDocumentNumber and zSalesDocumentNumber in PC10000, but I think the GL10001 index is the main one.

"IN" clauses are typically quite expensive compared to other techniques, but as you can't change the query itself then there's nothing you can do about that.

Without a doubt, you need to add suitable indexes

趁微风不噪 2024-08-03 03:16:16

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

The query is doing 2 table scans on the GL10001 table. From a quick look at the query (which is a bit hard to read) I would see if you have an index on the BACHNUMB column.

寂寞美少年 2024-08-03 03:16:16

执行计划非常清楚地表明,实际定位行一直是所花费的时间(没有繁琐的书签查找或聚合/重新排列任务),因此这肯定是索引问题。 将鼠标悬停在执行计划中的表扫描,然后检查工具提示中的“对象”,以查看正在使用哪些列。 确保它们被索引。

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

the execution plan shows pretty clearly that actually locating the rows is what's taking all the time (no cumbersome bookmark lookups, or aggregation/rearrange tasks), so it's quite positively going to be a question of indexing. hover the table scans in the execution plan, and check 'object' in the tooltip, to see what columns are being used. see to it that they're indexed.

you might also want to run a trace to sample some live data, and feed that to the database tuning advisor.

陪你到最终 2024-08-03 03:16:16

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

You could rewrite those sub-selects as a join, and add an index to GP01..GL10001 on BACHNUMB and JRNENTRY

逆流 2024-08-03 03:16:16

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

Since you can't change the query, the best thing you could do is make sure you have indexes on the columns that you're using for your joins (and subqueries). If you can think of a better query plan, you could provide that to SQL Server instead of letting it calculate its own (this is a very rare case).

最近可好 2024-08-03 03:16:16

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')) 

Replace the OR with a UNION ALL of two queries this should get shot of those spools

i.e. run the query once with something like this

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')) 
忘年祭陌 2024-08-03 03:16:16

除了添加索引之外,您还可以将 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

In addition to adding indexes, you can also convert the IN statements to EXISTS... something along these lines:

    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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文