【问题标题】:How to improve the performance of a SQL query even after adding indexes?添加索引后如何提高 SQL 查询的性能?
【发布时间】:2013-04-16 20:38:03
【问题描述】:

我正在尝试执行以下 sql 查询,但执行需要 22 秒。返回的项目数是 554192。我需要加快速度,并且已经在所有涉及的表中放置了索引。

SELECT mc.name                           AS MediaName, 
       lcc.name                          AS Country, 
       i.overridedate                    AS Date, 
       oi.rating, 
       bl1.firstname + ' ' + bl1.surname AS Byline, 
       b.id                              BatchNo, 
       i.numinbatch                      ItemNumberInBatch, 
       bah.changedatutc                  AS BatchDate, 
       pri.code                          AS IssueNo, 
       pri.name                          AS Issue, 
       lm.neptunemessageid               AS MessageNo, 
       lmt.name                          AS MessageType, 
       bl2.firstname + ' ' + bl2.surname AS SourceFullName, 
       lst.name                          AS SourceTypeDesc 
FROM   profiles P 
       INNER JOIN profileresults PR 
               ON P.id = PR.profileid 
       INNER JOIN items i 
               ON PR.itemid = I.id 
       INNER JOIN batches b 
               ON b.id = i.batchid 
       INNER JOIN itemorganisations oi 
               ON i.id = oi.itemid 
       INNER JOIN lookup_mediachannels mc 
               ON i.mediachannelid = mc.id 
       LEFT OUTER JOIN lookup_cities lc 
                    ON lc.id = mc.cityid 
       LEFT OUTER JOIN lookup_countries lcc 
                    ON lcc.id = mc.countryid 
       LEFT OUTER JOIN itembylines ib 
                    ON ib.itemid = i.id 
       LEFT OUTER JOIN bylines bl1 
                    ON bl1.id = ib.bylineid 
       LEFT OUTER JOIN batchactionhistory bah 
                    ON b.id = bah.batchid 
       INNER JOIN itemorganisationissues ioi 
               ON ioi.itemorganisationid = oi.id 
       INNER JOIN projectissues pri 
               ON pri.id = ioi.issueid 
       LEFT OUTER JOIN itemorganisationmessages iom 
                    ON iom.itemorganisationid = oi.id 
       LEFT OUTER JOIN lookup_messages lm 
                    ON iom.messageid = lm.id 
       LEFT OUTER JOIN lookup_messagetypes lmt 
                    ON lmt.id = lm.messagetypeid 
       LEFT OUTER JOIN itemorganisationsources ios 
                    ON ios.itemorganisationid = oi.id 
       LEFT OUTER JOIN bylines bl2 
                    ON bl2.id = ios.bylineid 
       LEFT OUTER JOIN lookup_sourcetypes lst 
                    ON lst.id = ios.sourcetypeid 
WHERE  p.id = @profileID 
       AND b.statusid IN ( 6, 7 ) 
       AND bah.batchactionid = 6 
       AND i.statusid = 2 
       AND i.isrelevant = 1 

查看执行计划时,我可以看到一个花费 42% 的步骤。有什么方法可以降低阈值,或者有什么方法可以提高整个查询的性能。

【问题讨论】:

  • 尝试查看(并可能在某处发布)实际执行计划。此外,我不确定您期望 20 表连接运行多快...
  • 问题是我需要这些查询能够在报表生成器 3 中运行,但是由于它们很慢,查询生成器会崩溃。
  • 老实说,我并不感到惊讶。您的联接中有 20 个表。然而,仅仅因为您在“所有涉及的表中”添加了索引并不意味着您放置了正确索引或者您的表设计首先是合理的。
  • 我在你的查询中也看到了一些奇怪的地方。内/左/内/左序列令人费解,而且您是否知道 - 例如 - 您在 batchactionhistory 上的 where 子句使其成为内连接,而不是外连接?
  • 我不得不使用左外连接,因为有些列可以有空值,如果我使用内连接,那么查询就不会返回任何结果。有没有什么地方可以上传执行计划,无论是xml还是图表?

标签: sql sql-server tsql


【解决方案1】:

删除配置文件表,因为它不需要并将 WHERE 子句更改为

WHERE  PR.profileid = @profileID

您在 batchactionhistory 表上有一个左外连接,但在 WHERE 子句中也有一个条件,将其转回内连接。将您的代码更改为:

LEFT OUTER JOIN batchactionhistory bah 
            ON b.id = bah.batchid
           AND bah.batchactionid = 6    

您不需要 batches 表,因为它用于连接其他可以直接连接的表,并在您的 SELECT 中显示 id,这在其他表中也可用。进行以下更改:

i.batchidid AS BatchNo, 

LEFT OUTER JOIN batchactionhistory bah 
           ON i.batchidid = bah.batchid 

是在包含大量数据但未编制索引的表中的连接或 WHERE 子句中使用的任何字段。如果是这样,请尝试在时间上为最大的表添加索引。

您是否需要结果中的每个字段 - 如果您可以丢失一个,或者您可能会进一步减少表格的数量。

【讨论】:

    【解决方案2】:

    首先,如果这不是一个存储过程,那就让它成为一个。需要 sql server 编译的文本很多。

    接下来,我的经验是“最坏做法”有时是个好主意。具体来说,我可以通过将大型查询拆分为几个或三个小型查询并组合结果来提高性能。

    如果此查询与 .net、coldfusion、java 等应用程序相关联,您也许可以在应用程序代码中进行拆分/重新组装。如果没有,临时表可能会派上用场。

    【讨论】:

      猜你喜欢
      • 2012-10-28
      • 1970-01-01
      • 2015-11-17
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多