【问题标题】:SQL Server Multiple Joins Are Taxing The CPUSQL Server 多连接占用 CPU
【发布时间】:2011-02-07 05:14:57
【问题描述】:

我在 SQL Server 2005 上有一个存储过程。它是从一个表函数中提取的,并且有两个连接。当使用负载测试运行查询时,它会在所有 16 个内核上 100% 杀死 CPU!我已经确定删除其中一个连接可以使查询运行良好,但都会占用 CPU。

 Select 
  SKey
 From 
  dbo.tfnGetLatest(@ID) a 
  left join [STAGING].dbo.RefSrvc b on 
   a.LID = b.ESIID
  left join [STAGING].dbo.RefSrvc c on 
   a.EID = c.ESIID 

感谢您的帮助,请注意连接发生在同一服务器上不同数据库中的同一表上。

【问题讨论】:

  • 您可以发布查询执行计划吗? SET SHOWPLAN_TEXT ON

标签: sql-server sql-server-2005 performance tsql user-defined-functions


【解决方案1】:

这可能会对问题有所了解。你能把第一个连接分成一个 CTE 吗?

类似这样的:

with FirstJoin(SKey,EID) as (
   select a.Skey,a.EID from 
       dbo.tfnGetLatest(@ID) a 
       left join [STAGING].dbo.RefSrvc b on a.LID = b.ESIID
)

从 FirstJoin fj 中选择 Skey left join [STAGING].dbo.RefSrvc c on fj.EID = c.ESIID

另外,由于您的两个联接都是左联接,它们如何缩小结果集?那个查询不等于select sKey from dbo.tfnGetLatest(@ID)吗?

【讨论】:

  • 它只从 TF 和连接中获取一条记录。
  • 如果它只有一条记录,并且 dbo.RefSrvc 在有问题的行上被索引,也许你应该尝试两个子选择而不是左连接。
【解决方案2】:

dbo.tfnGetLatest(@ID) 返回什么?它是内联表值还是多语句?

如果是多语句则

  • 这是优化者的黑匣子
  • 基数是一
  • udf 的结果没有统计数据

请看我的answer here for why udfs can be bad

【讨论】:

    【解决方案3】:

    那么你的执行计划有什么不同呢?这甚至使用索引吗?

    您是否尝试过使用 UNION all 代替(我假设您想要获取的是具有您当前查询不会给出的一个或另一个 id 的记录;不给出,所有 ti woudl 给出的是所有的完整列表skey 值,根本不需要加入。)

    Select  
        SKey 
    From  
        dbo.tfnGetLatest(@ID) a  
        left join [STAGING].dbo.RefSrvc b on  
            a.LID = b.ESIID 
    union all
    Select  
        SKey 
    From  
        dbo.tfnGetLatest(@ID) d  
        left join [STAGING].dbo.RefSrvc c on  
            d.EID = c.ESIID  
    

    如果不使用索引,它仍然可能效率不高,但它可能会返回更好的记录集。

    或者考虑将表值函数返回的值放入一个临时表中,在该表中可以对其进行索引,然后进行连接。

    【讨论】:

    • 这很奇怪,这只发生在负载测试或生产中。查询本身在一秒钟内运行。在负载测试时,我什至无法在所有 4 个 XEON 四核上达到 100% 之前获得 20 个用户。删除一个连接后,我将其增加到 2000 多个用户就好了。要回答您的问题,执行计划会更改以显示较少的连接,但总体上保持不变。它在问题表上使用聚集索引搜索,并在表函数上使用表扫描。
    • 它只从 TF 和连接中获取一条记录。
    • 当我只需要一个时,联合会引入两条记录,多个连接从两个不同的 ID 获取数据不重复。
    【解决方案4】:

    如果有一点示例输出,这会更清楚,但我会跳进去。这对你有什么用?

    SELECT SKey FROM dbo.tfnGetLatest(@ID)
    WHERE LID IN
        (SELECT ESIID from [STAGING].dbo.RefSrvc)
    AND EID IN
        (SELECT ESIID FROM [STAGING].dbo.RefSrvc)
    

    【讨论】:

      猜你喜欢
      • 2012-04-18
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      相关资源
      最近更新 更多