2015-10-13 106 views
0

我想从一个很好的大小(18,243,847行)的表中总结横幅广告视图。我需要在过去两年中收集意见。我试着给日期添加一个索引,并尝试下面查询的不同变体。大多数运行时间大约是25秒,但是当它在Web服务中传递时,目标页面超时。我知道问题与计数有关,但无法将该部分降至11秒以下。似乎不是很多,但为什么我的网络服务的问题?无论如何,首先要做的是,这个查询是否能够做到最好?优化缓慢运行计数查询

SELECT ba.adID, ba.name, ba.description, ba.startDate, ba.endDate, isNull(v.viewCount,0) AS viewCount, isNull(c.clickCount,0) AS clickCount 
FROM bannerAds ba 
    LEFT OUTER JOIN (SELECT adID, count(viewID) AS viewCount 
        FROM bannerAdsViews 
        WHERE viewDateTime IS NOT NULL AND viewDateTime >= DateAdd(yy, -2, GetDate()) 
        GROUP BY adID) v ON ba.adID = v.adID 
    LEFT OUTER JOIN (SELECT adID, count(viewID) AS clickCount 
        FROM bannerAdsViews 
        WHERE clickDateTime IS NOT NULL AND viewDateTime >= DateAdd(yy, -2, GetDate()) 
        GROUP BY adID) c ON ba.adID = c.adID 
WHERE viewCount > 0 
ORDER BY name ASC 
FOR XML RAW ('Banner'), ROOT ('Banners'); 
+0

不是每个人都回答的问题,但为什么不为每个横幅创建数据的每日总结视图,然后查询。因此,如果您随后将此更新作为计划作业,触发器或记录这些统计信息的一部分的一部分,而不是遍历1800万条记录,则只需查看几百条记录(取决于您的日期范围)每次要运行此查询时都必须继续完成计算。 –

+1

为了优化查询,我首先运行语句解释,否则只会优化错误的部分。 – AlexN

回答

2

此查询可能很难获得真正的良好性能。你正在总结很多数据。

但是,不需要两个子查询。如果我做的假设viewIDviewDateTime都在相同的记录都NULL,那么我觉得这个版本相当于:

SELECT ba.adID, ba.name, ba.description, ba.startDate, ba.endDate, 
     COALESCE(vc.viewCount, 0) as viewCount, 
     COALESCE(vc.clickCount, 0) as clickCount 
FROM bannerAds ba JOIN 
    (SELECT adID, count(viewDateTime) as viewCount, 
      count(clickDateTime) as clickCount 
     FROM bannerAdsViews 
     WHERE viewDateTime >= DateAdd(year, -2, GetDate())    
     GROUP BY adID 
    ) vc 
    ON ba.adID = v.adID 
WHERE viewCount > 0 
ORDER BY name ASC 
FOR XML RAW ('Banner'), ROOT ('Banners'); 

INNER JOIN可以代替LEFT JOIN,因为WHERE子句反正去除NULL值。

+0

看起来不错,把它降到10秒。我没有考虑将这两个统计结合成一个查询,这似乎很有意义。 COALESCE是更快还是只是首选还是无效? –

+0

看起来'ISNULL'有点快。见http://stackoverflow.com/questions/2287642/which-is-quicker-coalesce-or-isnull和http://dba.stackexchange.com/questions/4274/performance-difference-for-coalesce-versus-isnull 。 – ForguesR

+0

@ConnieDeCinko。 。 。我更喜欢'coalesce()',因为它是ANSI标准并接受两个以上的参数。 SQL Server对'isnull()'有更好的实现(因为第一个参数不被计算两次)。对于只读取列,差异可以忽略不计。当第一个参数很昂贵时,比如函数all或子查询,由于性能原因,'isnull()'肯定是首选。 –