4

我有一个查询需要大约 11 秒才能运行一个日期。我想多天运行相同的查询。换句话说,我希望能够返回多天的快照。这是我的原始查询:

SELECT 
    COUNT(*) AS 'Number of Cars',
    d.ManufacturerName AS 'Make',
    d.Name AS 'Model', 
    c.name AS 'Car Class'
FROM CarRating a 
    INNER JOIN OwnedCar b ON a.OwnedCarID = b.OwnedCarID
    INNER JOIN CarClass c ON a.CarClassID = c.CarClassID
    INNER JOIN BaseCar d ON b.BaseCarID = d.BaseCarID

WHERE 
    @myDate < a.ExpiredWhen AND @myDate  >= a.EffectiveWhen 
GROUP BY 
    d.Name, c.name,d.ManufacturerName

就像我提到的那样,查询需要 11 秒。为了对多个日期运行此查询,我使用日期表并将其交叉应用于上述查询:

SELECT [DATE], b.* FROM DimDate 
CROSS APPLY
    (SELECT 
        COUNT(*) AS 'Number of Cars',
        d.ManufacturerName AS 'Make',
        d.Name AS 'Model', 
        c.name AS 'Car Class'
    FROM CarRating a 
        INNER JOIN OwnedCar b ON a.OwnedCarID = b.OwnedCarID
        INNER JOIN CarClass c ON a.CarClassID = c.CarClassID
        INNER JOIN BaseCar d ON b.BaseCarID = d.BaseCarID

    WHERE 
    dimDate.Date < a.ExpiredWhen AND dimDate.Date >= a.EffectiveWhen    
    GROUP BY 
    d.Name, c.name,d.ManufacturerName) b

 WHERE DimDate.Date between @StartDate and @EndDate

这个查询即使是一天也需要 49 秒。为什么这么慢?有没有更好的方法来做到这一点?

4

5 回答 5

2

您的查询速度较慢,因为它正在加入维度表,大大增加了正在处理的数据量。您可以通过确保您具有适当的索引来修复此查询:

  • 拥有汽车(OwnedCarId)
  • 汽车类(汽车类 ID)
  • BaseCare(BaseCareID)
  • CarRating(EffectiveWhen, ExpiredWhen)

如果这没有帮助,那么您将需要重新考虑查询。有另一种写法,但索引可能更简单地解决问题。

于 2012-10-23T18:34:40.243 回答
1

它真的需要交叉应用/子查询吗?似乎它正在以这种方式做更多的工作。不能是左连接吗?

SELECT 
    dimDate.[Date]
    COUNT(1) AS 'Number of Cars',
    d.ManufacturerName AS 'Make',
    d.Name AS 'Model', 
    c.name AS 'Car Class'
FROM DimDate
LEFT OUTER JOIN CarRating a ON dimDate.[Date] < a.ExpiredWhen AND dimDate.[Date] >= a.EffectiveWhen 
LEFT OUTER JOIN OwnedCar b ON a.OwnedCarID = b.OwnedCarID
LEFT OUTER JOIN CarClass c ON a.CarClassID = c.CarClassID
LEFT OUTER JOIN BaseCar d ON b.BaseCarID = d.BaseCarID
GROUP BY dimDate.[Date], d.Name, c.name,d.ManufacturerName
于 2012-10-23T21:53:07.277 回答
0

您可以尝试如下修改您的查询,然后分享结果(如果您观察到任何改进)

SELECT [DATE], b.* FROM DimDate 
CROSS APPLY
    (SELECT 
        **COUNT(1)** AS 'Number of Cars',
        d.ManufacturerName AS 'Make',
        d.Name AS 'Model', 
        c.name AS 'Car Class'
    FROM CarRating a 
        INNER JOIN OwnedCar b ON a.OwnedCarID = b.OwnedCarID
        **AND  dimDate.Date < a.ExpiredWhen AND dimDate.Date >= a.EffectiveWhen**   
        INNER JOIN CarClass c ON a.CarClassID = c.CarClassID
        INNER JOIN BaseCar d ON b.BaseCarID = d.BaseCarID

    GROUP BY 
    d.Name, c.name,d.ManufacturerName) b

 WHERE DimDate.Date between @StartDate and @EndDate
于 2012-10-23T19:13:14.477 回答
0

我对CROSS APPLY自己不熟悉,但你不能ExpiredWhen按范围添加和分组,如下所示:

SELECT
     a.ExpiredWhen AS dimDate
   , COUNT(*) AS 'Number of Cars'
   , d.ManufacturerName AS 'Make'
   , d.Name AS 'Model'
   , c.name AS 'Car Class' 
FROM CarRating a
INNER JOIN OwnedCar b ON a.OwnedCarID = b.OwnedCarID
INNER JOIN CarClass c ON a.CarClassID = c.CarClassID
INNER JOIN BaseCar d ON b.BaseCarID = d.BaseCarID  
WHERE a.ExpiredWhen between @StartDate AND @EndDate
GROUP BY
   a.ExpiredWhen, d.Name, c.name, d.ManufacturerName
于 2012-10-23T18:35:02.510 回答
0

当在医疗数据集中的大表上使用时,我在 MS SQL 服务器中使用 CROSS APPLY 时也有类似的体验。我说的是添加 CROSS APPLY 后执行时间增加了几个数量级。

经过一番探索,我发现使用 PIVOT 非常有效,将查询从 > 18 小时缩短到 2 分钟以下(!)所以我想我会分享这个 2c 技巧。乔。

于 2016-01-27T19:42:36.850 回答