SQL效率不够,需要调优协助

时间:2017-03-08 02:32:45

标签: sql sql-server

我们有一些SQL可以在较小的数据量上使用,但是一旦我们扩展到从较大的卷中进行选择就会很差。是否有更快的替代风格来实现与下面相同的输出?我的想法是拉回一个唯一的行来获取最新版本的数据...... SQL确实引用了另一个视图,但是这个视图运行得非常快 - 所以我们期望问题出现在下面,并且想尝试不同的方法

SELECT *
FROM 
   (SELECT (select CustomerId from PremiseProviderVersionsToday 
            where PremiseProviderId = b.PremiseProviderId) as CustomerId, 
            c.D3001_MeterId, b.CoreSPID, a.EnteredBy, 
            ROW_NUMBER() OVER (PARTITION BY b.PremiseProviderId
            ORDER BY a.effectiveDate DESC) AS rowNumber
    FROM PremiseMeterProviderVersions a, PremiseProviders b, 
         PremiseMeterProviders c
    WHERE (a.TransactionDateTimeEnd IS NULL 
    AND a.PremiseMeterProviderId = c.PremiseMeterProviderId 
    AND b.PremiseProviderId = c.PremiseProviderId)
   ) data
WHERE data.rowNumber = 1

3 个答案:

答案 0 :(得分:1)

正如Bilal Ayub所说,相关子查询可能会导致性能问题。有关详细信息,请参阅here。以下是我的建议:

  1. 将所有内容更改为显式联接(ANSI标准)
  2. 使用比单个字符更具描述性的别名(这主要是为了帮助读者了解每个表的作用)
  3. 数据子查询转换为临时表或cte(临时表和ctes通常比子查询执行得更好)
  4. 注意:通常,您应该显式创建并插入临时表,但我选择不在此处执行此操作,因为我不知道列的数据类型。

    SELECT d.CustomerId
         , c.D3001_MeterId
         , b.CoreSPID
         , a.EnteredBy
         , rowNumber = ROW_NUMBER() OVER(PARTITION BY b.PremiseProviderId ORDER BY a.effectiveDate DESC)
    INTO #tmp_RowNum
    FROM PremiseMeterProviderVersions a 
    JOIN PremiseMeterProviders        c ON c.PremiseMeterProviderId = a.PremiseMeterProviderId  
    JOIN PremiseProviders             b ON b.PremiseProviderId = c.PremiseProviderId
    JOIN PremiseProviderVersionsToday d ON d.PremiseProviderId = b.PremiseProviderId
    WHERE a.TransactionDateTimeEnd IS NULL
    
    SELECT * 
    FROM #tmp_RowNum
    WHERE rowNumber = 1
    

答案 1 :(得分:0)

您正在运行将在循环中运行的相关查询,如果表的大小很小,它会更快,我建议更改它并尝试加入表以获取customerid。

(从PremiseProviderVersionsToday选择CustomerId,其中PremiseProviderId = b.PremiseProviderId)作为CustomerId

答案 2 :(得分:0)

考虑派生表,包括通过 PremiseProviderId 和单元级查询计算最大 EffectoveDate 的聚合查询,每个使用显式连接(当前ANSI SQL标准),而不是隐含的目前使用:

SELECT data.*
FROM 
   (SELECT t.CustomerId, c.D3001_MeterId, b.CoreSPID, a.EnteredBy, 
           b.PremiseProviderId, a.EffectiveDate
    FROM PremiseMeterProviders c 
    INNER JOIN PremiseMeterProviderVersions a
        ON a.PremiseMeterProviderId = c.PremiseMeterProviderId 
        AND a.TransactionDateTimeEnd IS NULL 
    INNER JOIN PremiseProviders b
        ON b.PremiseProviderId = c.PremiseProviderId    
    INNER JOIN PremiseProviderVersionsToday t 
        ON t.PremiseProviderId = b.PremiseProviderId
   ) data
INNER JOIN
   (SELECT b.PremiseProviderId, MAX(a.EffectiveDate) As MaxEffDate
    FROM PremiseMeterProviders c 
    INNER JOIN PremiseMeterProviderVersions a
        ON a.PremiseMeterProviderId = c.PremiseMeterProviderId 
        AND a.TransactionDateTimeEnd IS NULL 
    INNER JOIN PremiseProviders b
        ON b.PremiseProviderId = c.PremiseProviderId 
    GROUP BY b.PremiseProviderId   
   ) agg
ON data.PremiseProviderId = agg.PremiseProviderId
AND data.EffectiveDate = agg.MaxEffDate