如果只有在结果集很小的情况下,当连接比dense_rank快时,如何优化这两种情况?

时间:2014-01-23 14:54:41

标签: tsql query-optimization

未经过滤时,FeedDeliveryNutrients.NutrientID超过150,000行的dense_rank比使用Nutrients.ID上的row_number和使用已加入的行号加入Nutrients快3.5倍。过滤到特定鸡群时,加入row_number的速度提高了9倍。

是否有任何优化技术可以在单个查询中充分利用两个世界


未经过滤时最快(返回150,000行):

select
    FeedDeliveries.FlockID,
    FeedDeliveryID,
    DeliveryLb,
    Bin,
    DeliveryDate,
    FormulaID,
    FeedEnergy,
    Nutrient1, Nutrient2, Nutrient3, Nutrient4, Nutrient5, Nutrient6, Nutrient7, Nutrient8, Nutrient9, Nutrient10, Nutrient11, Nutrient12, Nutrient13, Nutrient14, Nutrient15
from (
    select
        FeedDeliveryID,
        sum(case when dense_rank = 1 then Amount end) as Nutrient1,
        sum(case when dense_rank = 2 then Amount end) as Nutrient2,
        sum(case when dense_rank = 3 then Amount end) as Nutrient3,
        sum(case when dense_rank = 4 then Amount end) as Nutrient4,
        sum(case when dense_rank = 5 then Amount end) as Nutrient5,
        sum(case when dense_rank = 6 then Amount end) as Nutrient6,
        sum(case when dense_rank = 7 then Amount end) as Nutrient7,
        sum(case when dense_rank = 8 then Amount end) as Nutrient8,
        sum(case when dense_rank = 9 then Amount end) as Nutrient9,
        sum(case when dense_rank = 10 then Amount end) as Nutrient10,
        sum(case when dense_rank = 11 then Amount end) as Nutrient11,
        sum(case when dense_rank = 12 then Amount end) as Nutrient12,
        sum(case when dense_rank = 13 then Amount end) as Nutrient13,
        sum(case when dense_rank = 14 then Amount end) as Nutrient14,
        sum(case when dense_rank = 15 then Amount end) as Nutrient15
    from (select *, dense_rank() over (partition by FeedDeliveryID order by NutrientID) as dense_rank from dbo.FeedDeliveryNutrients) n
    group by FeedDeliveryID
) pvt
join dbo.FeedDeliveries on FeedDeliveries.ID = FeedDeliveryID


使用dbo.FeedDeliveries.FlockID过滤时速度最快(返回约100行):

select
    FeedDeliveries.FlockID,
    FeedDeliveryID,
    DeliveryLb,
    Bin,
    DeliveryDate,
    FormulaID,
    FeedEnergy,
    Nutrient1, Nutrient2, Nutrient3, Nutrient4, Nutrient5, Nutrient6, Nutrient7, Nutrient8, Nutrient9, Nutrient10, Nutrient11, Nutrient12, Nutrient13, Nutrient14, Nutrient15
from (
    select
        FeedDeliveryID,
        sum(case when n.row_number = 1 then Amount end) as Nutrient1,
        sum(case when n.row_number = 2 then Amount end) as Nutrient2,
        sum(case when n.row_number = 3 then Amount end) as Nutrient3,
        sum(case when n.row_number = 4 then Amount end) as Nutrient4,
        sum(case when n.row_number = 5 then Amount end) as Nutrient5,
        sum(case when n.row_number = 6 then Amount end) as Nutrient6,
        sum(case when n.row_number = 7 then Amount end) as Nutrient7,
        sum(case when n.row_number = 8 then Amount end) as Nutrient8,
        sum(case when n.row_number = 9 then Amount end) as Nutrient9,
        sum(case when n.row_number = 10 then Amount end) as Nutrient10,
        sum(case when n.row_number = 11 then Amount end) as Nutrient11,
        sum(case when n.row_number = 12 then Amount end) as Nutrient12,
        sum(case when n.row_number = 13 then Amount end) as Nutrient13,
        sum(case when n.row_number = 14 then Amount end) as Nutrient14,
        sum(case when n.row_number = 15 then Amount end) as Nutrient15
    from dbo.FeedDeliveryNutrients
    join (select *, row_number() over (order by ID) as row_number from dbo.Nutrients) n on n.ID = NutrientID
    group by FeedDeliveryID
) pvt
join dbo.FeedDeliveries on FeedDeliveries.ID = FeedDeliveryID

1 个答案:

答案 0 :(得分:0)

你已经得到了答案。针对最关键的情况进行优化。

从一开始我就可以对150.000行的场景使用优化,但你必须在实际的生产服务器上嗅一下。如果150.000只发生几次/周,并且100行生病了多次/分钟,这对你来说更重要。