Sql 计算列的排序或筛选速度太慢

Sql 计算列的排序或筛选速度太慢,sql,sql-server,tsql,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 ma

我有一个用于排序或筛选的计算列,但当有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

我已尝试重新编写您的加入:

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;

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

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

这能帮助您理解计算列吗?


如果dB大小和写入时间不是问题,我会考虑对架构进行反规范化。这将消除以写入时间为代价计算函数的需要。例如,日期组x价格x折扣可以在一个表中。该表可以是唯一的,并且可以按dategroupid进行聚集索引以进行查找

执行计划中说78%的成本是在:【日期】【PK_日期】请将执行计划共享为xml什么是【日期】?我没有看到任何[日期]。我只看到一个[DateGroup]。将标量函数转换为表值函数是一个选项吗?一般来说,TVF内嵌式TVF最好比标量对应物更快。[Date]是[AvailableDates]表,我会编辑问题以正确显示它。@Serg我会检查一下,看看这是否适合我。我还考虑了当一个相关列发生变化时更新该列的触发器,这使我的查询速度提高了近一倍。但还是不够快。从1:59降到1:05很好。另一件事是参数嗅探。我不知道它是否真的会产生影响。它对存储过程影响很大。你所需要做的就是声明@id1、@group1作为输入参数,然后在内部开始分别将它们设置为@id、@group是的,我也是这么想的,但问题是价格仍然不同,取决于有多少预订。虽然重新编写类似“Prabhat G”的函数有助于提高速度,但速度仍然不够快。因此,在与客户交谈之后,我们决定更改模式并对其进行非规范化。
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;