Stored Proc /Table 索引改进

Stored Proc /Table Index Improvement

我正在寻找有关我们在应用程序中使用的存储过程的评论。它被调用了很多,我认为还有改进的余地。我还想看看给 Team 和 Opp 添加索引是否对 SP 有帮助。

我们在 Azure 数据库上运行。

table 的架构如下:

CREATE TABLE [dbo].[TeamHistoryMatchUps] (
    [Id]              UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
    [Team]            NVARCHAR (100)   NOT NULL,
    [Opp]             NVARCHAR (100)   NOT NULL,
    [Result]          INT              NOT NULL,
    [MatchResultTime] DATETIME2 (7)    DEFAULT (getdate()) NOT NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)
);

这是 SP:

CREATE PROCEDURE [dbo].[up_GetTeamPercentagev2]
@Team NVARCHAR(100),
@Opp NVARCHAR(100) 
AS
begin
set nocount ON
declare

@TotalResult INT,
@TeamResult INT


--Total Matchups
Set  @TotalResult = (SELECT count(*)  FROM TeamHistoryMatchUps
WHERE (Team = @Team OR Opp = @Team) AND (Team = @Opp OR Opp = @Opp)
AND Result = 1)

Set  @TeamResult = (SELECT COUNT(*) FROM TeamHistoryMatchUps
WHERE Team = @Team and Opp = @Opp
AND Result = 1)

SELECT (@TeamResult * 100 / @TotalResult) AS Percentage

exit_proc:
end

我应该提到我担心插入,因为就在这个 sp 被调用之前插入到 table 中,然后随着时间的推移进行调用以获得这场比赛的获胜百分比。

在使用显示执行计划几次后,我确实添加了两个非聚集索引。

GO
CREATE NONCLUSTERED INDEX [[IX_MatchUps]
    ON [dbo].[TeamHistoryMatchUps]([Result] ASC)
    INCLUDE([Team], [Opp]);
GO
CREATE NONCLUSTERED INDEX [IX_MatchupsTeamOpp]
    ON [dbo].[TeamHistoryMatchUps]([Team] ASC, [Opp] ASC)
    INCLUDE([Result], [MatchResultTime], [MatchUpId]);

这 table 将进入百万行。目前在120k左右。

我在每个团队的 TeamHistoryMatchUps 中添加了 2 条记录,结果为 0 或 1。我试图让它非常简单,以便上面的查询可以。

CREATE PROCEDURE [dbo].[up_GetTeamPercentage]
    @Team NVARCHAR(100),
    @Opp NVARCHAR(100)
AS
SELECT 
    SUM(SIGN(result)) * 100 / COUNT(*) 
    AS Percentage
    FROM TeamHistoryMatchUps
    WHERE Team = @Team AND Opp = @Opp

但认为更少的写入和更复杂的读取(在 SP 中)将是更好的方法。

如果您不担心插入速度变慢,我会说继续添加索引以获得更好的选择性能。

索引还应过滤结果为 1 的结果。

CREATE NONCLUSTERED INDEX [IX_TeamHistoryMatchUps_team_opp] 
ON [dbo].[TeamHistoryMatchUps] ([Team],[Opp])
WHERE result=1

我认为这应该会减少访问(与此同时,我正在尝试看看是否可以只使用一个 SELECT)。建议的索引应该有所帮助。

--Total Matchups
SELECT @TeamResult = COUNT(*) FROM TeamHistoryMatchUps
WHERE  Result = 1
    AND Team = @Team and Opp = @Opp

SELECT @TotalResult = count(*)  
FROM TeamHistoryMatchUps
WHERE Opp = @Team AND Team = @Opp 
AND Result = 1

SET @TotalResult= @TotalResult+@TeamResult

答案是,它取决于 TeamHistoryMatchUps table 中的记录数,以及每一列中有多少不同的值。如果 table 中没有大量记录,查询优化器可能仍会创建一个涉及索引扫描的执行计划(读取索引中的每个叶记录以查找匹配项)。这并不比完整 table 扫描快多少。

如果有很多记录并且您在团队中搜索的值和 opp 索引将 return 大约 15% 或更少的行,查询优化器可能会选择使用通过索引查找索引。在这种情况下,会有一个性能提升。

将存储过程参数重新声明为本地参数。它处理参数嗅探,当 WITH RECOMPILE 不起作用时,这也会提高性能(来源:TBD)

创建过程 [dbo].[up_GetTeamPercentagev2] @Team NVARCHAR(100), @Opp NVARCHAR(100) 作为 开始 设置 nocount ON 声明</p> <p>@localTeam NVARCHAR(100), @localOpp NVARCHAR(100), @TotalResult INT, @TeamResult INT</p> <p>设置@Team = @localTeam SET @Opp = @localOpp</p> <p>--总对局 设置 @TotalResult = (SELECT count(*) FROM TeamHistoryMatchUps WHERE (Team = @localTeam OR Opp = @localTeam) AND (Team = @localOpp OR Opp = @localOpp) AND 结果 = 1)</p> <p>设置@TeamResult = (SELECT COUNT(*) 来自 TeamHistoryMatchUps WHERE Team = @localTeam 和 Opp = @localOpp AND 结果 = 1)</p> <p>SELECT (@TeamResult * 100 / @TotalResult) AS 百分比</p> <p>exit_proc: 结束

***从未在 Azure DB 上尝试过这个