计算列在排序或过滤方面太慢

时间:2017-07-10 08:52:02

标签: sql sql-server tsql

我有一个用于排序或过滤的计算列,但是当有1000多行时,执行时间太长。

此查询适用于预订系统,可根据价格订购可用日期。

这是数据库架构:

AvailableDates has one DateGroup
DateGroup has many Prices
DateGroup has many Discounts
Each Discount contains 3 columns. MinPerson, MaxPerson, DiscountPercentage
AvailableDates has many BookingGroups.
BookingGroups has many Bookings.
BookingGroups has a computed column that calculates how many bookings there are.

AvailableDate的计算价格列由函数计算。价格由;确定;

Get Max Price from Prices
Get How many booking there is
Get discount that will be applied depending on number of bookings.

这是函数查询:

FUNCTION [dbo].[fn_datePrice]
    (
      @id INT,
      @groupId INT
    )
RETURNS decimal(19, 5)
AS
    BEGIN
    declare @price decimal(19,5), @discount decimal(19,5), @numOfPeople INT
    SELECT @numOfPeople= b.NumberOfPeople FROM BookingGroup b
                WHERE b.DateId = @id and b.Status != 'Expired';

    if (@numOfPeople is null or @numOfPeople < 1)
        SET @numOfPeople = 1;

    SELECT @price = MAX(pr.Price),
        @discount = disc.DiscountPercentage
    FROM DateGroup dateGroup
    LEFT JOIN Prices pr on pr.GroupId = dateGroup.Id
    LEFT JOIN Discounts disc on disc.GroupId = dateGroup.Id and @numOfPeople BETWEEN disc.MinPeople and disc.MaxPeople
    WHERE dateGroup.Id = @groupId
    GROUP BY dateGroup.Id, disc.DiscountPercentage;

    if (@discount is null)
        return @price
    return @price * (100 - @discount) / 100
    END;
GO

执行计划表示78%的费用已开启:密钥查找(已集群)[可用日期]。[PK_AvailableDate]

我的活动监视器说这个查询是最昂贵的查询:

SELECT @price = MAX(pr.Price),
            @discount = disc.DiscountPercentage
        FROM DateGroup dateGroup
        LEFT JOIN Prices pr on pr.GroupId = dateGroup.Id
        LEFT JOIN Discounts disc on disc.GroupId = dateGroup.Id and @numOfPeople BETWEEN disc.MinPeople and disc.MaxPeople
        WHERE dateGroup.Id = @groupId
        GROUP BY dateGroup.Id, disc.DiscountPercentage;

3 个答案:

答案 0 :(得分:1)

这可以帮助您理解计算列吗? http://sqlblog.com/blogs/ben_nevarez/archive/2009/08/10/the-query-optimizer-and-computed-columns.aspx

如果数据库大小和写入时间不是问题,我会考虑对模式进行非规范化。这将消除以写入时间为代价计算功能的需要。例如,dategroup x price x discount可以在一个表中。桌子可以是独一无二的。聚集由dategroupid索引以查找。

答案 1 :(得分:0)

我试图重新编写您的加入:

SELECT @price = MAX(pr.Price),
            @discount = disc.DiscountPercentage
FROM DateGroup dateGroup
LEFT JOIN Prices pr on pr.GroupId = dateGroup.Id
LEFT JOIN Discounts disc on disc.GroupId = dateGroup.Id 
WHERE   (@numOfPeople BETWEEN disc.MinPeople and disc.MaxPeople)
        AND (dateGroup.Id = @groupId)
GROUP BY dateGroup.Id, disc.DiscountPercentage;

尝试让我知道它是否会产生影响。

答案 2 :(得分:0)

总是可以尝试将此函数重写为内联,您需要记住多行函数比内联函数慢得多。

相关问题