存储过程/表索引改进

时间:2017-04-14 12:40:21

标签: tsql stored-procedures azure-sql-database table-index

我正在寻找我们在应用程序中使用的存储过程的一些注释。它被召唤了很多,我认为还有改进的余地。我还希望看看为Team和Opp添加索引是否有助于SP。

我们在Azure数据库上运行它。

表的架构如下:

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之前调用一个插入到表中然后调用以在这个匹配中获得win%。

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

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]);

此表将获得百万行。目前它在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中)将是更好的方法。

4 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

我认为这应该减少访问(同时,我试图看看是否可以只使用一个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

答案 2 :(得分:0)

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

如果有大量记录并且您在团队中搜索的值和opp索引将返回大约15%或更少的行,则查询优化器可能会选择通过以下方式使用索引索引寻求。在这种情况下,将会有性能提升。

答案 3 :(得分:0)

将sproc params重新声明为本地参数。它处理param嗅探,当WITH RECOMPILE没有帮助时,这也提高了性能(来源:待定)

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

@localTeam NVARCHAR(100), @localOpp NVARCHAR(100), @TotalResult INT, @TeamResult INT

Set @Team = @localTeam SET @Opp = @localOpp

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

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

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

exit_proc: end

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