我有一个简单的存储过程,它接受一堆参数来更新表中的现有记录。使用其他存储过程创建和删除记录只需要很少的时间来执行。但是,执行更新存储过程最多需要60秒,我无法理解为什么。
我已经尝试过这篇SO文章的提案,但没有任何运气:SQL Server: Query fast, but slow from procedure
这是最初的SP:
CREATE PROCEDURE [dbo].sp_Update
@OwnerId uniqueidentifier,
@DealId uniqueidentifier,
@Title nvarchar(250),
@Description nvarchar(MAX),
@ProjectValue money,
@Country nvarchar(250),
@CountryRegion nvarchar(MAX),
@WorldRegion nvarchar(250),
@MarketSector nvarchar(250),
@ProjectStage nvarchar(250),
@CreationDate datetime,
@ExpiryDate datetime,
@ImageFilePath nvarchar(max),
@IsActive bit,
@IsDeleted bit
AS
BEGIN
update SomeTable set
OwnerId = @OwnerId,
Title = @Title,
Description = @Description,
ProjectValue = @ProjectValue,
Country = @Country,
CountryRegion = @CountryRegion,
WorldRegion = @WorldRegion,
MarketSector = @MarketSector,
ProjectStage = @ProjectStage,
CreationDate = @CreationDate,
ExpiryDate = @ExpiryDate,
ImageFilePath = @ImageFilePath,
IsActive = @IsActive,
IsDeleted = @IsDeleted
where DealId = @DealId
END
在逐一尝试上述文章中的所有建议之后,我最终得到了这个:
CREATE PROCEDURE [dbo].sp_Update2
@OwnerId uniqueidentifier,
@DealId uniqueidentifier,
@Title nvarchar(250),
@Description nvarchar(MAX),
@ProjectValue money,
@Country nvarchar(250),
@CountryRegion nvarchar(MAX),
@WorldRegion nvarchar(250),
@MarketSector nvarchar(250),
@ProjectStage nvarchar(250),
@CreationDate datetime,
@ExpiryDate datetime,
@ImageFilePath nvarchar(max),
@IsActive bit,
@IsDeleted bit
WITH RECOMPILE
AS
BEGIN
set quoted_identifier off
SET ansi_nulls on
Declare @tempOwnerId uniqueidentifier
Declare @tempDealId uniqueidentifier
Declare @tempTitle nvarchar(250)
Declare @tempDescription nvarchar(MAX)
Declare @tempProjectValue money
Declare @tempCountry nvarchar(250)
Declare @tempCountryRegion nvarchar(MAX)
Declare @tempWorldRegion nvarchar(250)
Declare @tempMarketSector nvarchar(250)
Declare @tempProjectStage nvarchar(250)
Declare @tempCreationDate datetime
Declare @tempExpiryDate datetime
Declare @tempImageFilePath nvarchar(max)
Declare @tempIsActive bit
Declare @tempIsDeleted bit
set @tempOwnerId = @OwnerId
set @tempDealId = @DealId
set @tempTitle = @Title
set @tempDescription = @Description
set @tempProjectValue = @ProjectValue
set @tempCountry = @Country
set @tempCountryRegion = @CountryRegion
set @tempWorldRegion = @WorldRegion
set @tempMarketSector = @MarketSector
set @tempProjectStage = @ProjectStage
set @tempCreationDate = @CreationDate
set @tempExpiryDate = @ExpiryDate
set @tempImageFilePath = @ImageFilePath
set @tempIsActive = @IsActive
set @tempIsDeleted = @IsDeleted
update SomeTable set
OwnerId = @tempOwnerId,
Title = @tempTitle,
Description = @tempDescription,
ProjectValue = @tempProjectValue,
Country = @tempCountry,
CountryRegion = @tempCountryRegion,
WorldRegion = @tempWorldRegion,
MarketSector = @tempMarketSector,
ProjectStage = @tempProjectStage,
CreationDate = @tempCreationDate,
ExpiryDate = @tempExpiryDate,
ImageFilePath = @tempImageFilePath,
IsActive = @tempIsActive,
IsDeleted = @tempIsDeleted
where DealId = @tempDealId
set quoted_identifier off
SET ansi_nulls on
END
请注意,proc中的ANSI_NULLS和QUOTED_IDENTIFIER以及CREATE而不是ALTER的有趣定位,因为Visual Studio 2015无法像在SSMS中那样处理命令。
我不知道如何加快速度,并且不想沿着将其转换为手动连接字符串的路线,因为一些参数可以接受会使查询不安全的字符(即单引号等)
我也在C#.NET中调用通过Dapper执行存储过程,如果这有任何区别的话。
有什么想法吗?
更新: 这是带有当前索引的表定义:
CREATE TABLE [dbo].[SomeTable] (
[DealId] UNIQUEIDENTIFIER NOT NULL,
[OwnerId] UNIQUEIDENTIFIER NOT NULL,
[Title] NVARCHAR (250) NOT NULL,
[Description] NVARCHAR (MAX) NOT NULL,
[ProjectValue] MONEY NOT NULL,
[ProjectStage] NVARCHAR (250) NOT NULL,
[Country] NVARCHAR (250) NOT NULL,
[CountryRegion] NVARCHAR (MAX) NULL,
[WorldRegion] NVARCHAR (250) NOT NULL,
[MarketSector] NVARCHAR (250) NOT NULL,
[ImageFilePath] NVARCHAR (MAX) NULL,
[CreationDate] DATETIME NOT NULL,
[ExpiryDate] DATETIME NOT NULL,
[IsDeleted] BIT DEFAULT ((0)) NOT NULL,
[IsActive] BIT DEFAULT ((0)) NOT NULL,
PRIMARY KEY CLUSTERED ([DealId] ASC)
);
GO
CREATE NONCLUSTERED INDEX [deal_owners]
ON [dbo].[SomeTable]([OwnerId] ASC);
GO
CREATE NONCLUSTERED INDEX [deal_ids]
ON [dbo].[SomeTable]([DealId] ASC);
答案 0 :(得分:0)
假设DealId是唯一的 - 你每次只更新一行,我不认为这是参数嗅探问题,当某些事情在某个地方以及在其他地方缓慢运行时,这是通常的怀疑。
字段DealId是否已编入索引,是索引中的第一个(或唯一)列?
您是否检查过没有阻塞导致程序运行缓慢?
您是否看过执行的实际计划,如果发生了奇怪的事情,而不是索引搜索+键查找。
Ansi_nulls或quoted_identifier不会影响这样的计划。人们认为这会影响计划,但通常只是计划重复使用,当会话选项不匹配时会创建不同的计划。