我有一个严重的性能问题。SQL Server 2008插入后运行触发器,更新锁定原始表
我有一个数据库(与此问题有关),2个表。
1表包含具有某些全局信息的字符串。第二个表格包含剥离到每个单词的字符串。所以这个字符串就像在第二个表中逐个索引一样。
第二个表中的数据的有效性不如第一个表中的数据的有效性那么重要。
由于第一个表可以像1 * 10^6记录一样增长,而第二个表对于1个字符串具有平均10个单词的平均值可以像1 * 10^7记录一样增长,所以我使用nolock来读取第二个这使我可以自由地插入新记录而不锁定它(期望在两个表上有很多读取)。
我有一个脚本,不断向MERGE语句中的第一个表添加和更新行。平均来说,合并的数据每次像20个字符串,脚本每5秒钟运行一次。
在第一个表上,我有一个触发器,它在Insert或Update上被调用,它接受新插入或更新的数据,并调用一个存储过程来确保数据在第二个表中被索引。 (这需要一些相当长的时间)。
问题是,当触发器disbaled时,读取第一个表发生在几个毫秒。但是,启用触发器时,如果在更新时尝试读取第一个表,您的运气不好,我们的Web服务器会在10秒后给您一个超时值(反正是这样)。
我可以从这个部分得知,当运行触发器时,第一个表被保持(部分)在一个锁中,直到触发完成。
你认为,如果我是对的,有没有简单的方法呢?
提前致谢!
按照要求:
ALTER TRIGGER [dbo].[OnFeedItemsChanged]
ON [dbo].[FeedItems]
AFTER INSERT,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @id int;
SELECT @id = ID FROM INSERTED;
IF @id IS NOT NULL
BEGIN
DECLARE @title nvarchar(MAX);
SELECT @title = Title FROM INSERTED;
DECLARE @description nvarchar(MAX);
SELECT @description = [Description] FROM INSERTED;
SELECT @title = dbo.RemoveNonAlphaCharacters(@title)
SELECT @description = dbo.RemoveNonAlphaCharacters(@description)
-- Insert statements for trigger here
EXEC dbo.usp_index_itemstring @id, @title;
EXEC dbo.usp_index_itemstring @id, @description;
END
END
的FeedItems表由该查询填充:
MERGE INTO FeedItems i
USING @newitems d ON i.Service = d.Service AND i.GUID = d.GUID
WHEN matched THEN UPDATE
SET i.Title = d.Title,
i.Description = d.Description,
i.Uri = d.Uri,
i.Readers = d.Readers
WHEN NOT matched THEN INSERT
(Service, Title, Uri, GUID, Description, Readers)
VALUES
(d.Service, d.Title, d.Uri, d.GUID, d.Description, d.Readers);
的存储过程:IndexItemStrings被填充的第二个表,执行该进程内确实需要他的时间。问题在于执行此触发器时。适用于FeedItems表的查询大多超时(甚至谁不使用第二个表的查询)
第一个表:
USE [ICI]
GO
/****** Object: Table [dbo].[FeedItems] Script Date: 04/09/2010 15:03:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FeedItems](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Service] [int] NOT NULL,
[Title] [nvarchar](max) NULL,
[Uri] [nvarchar](max) NULL,
[Description] [nvarchar](max) NULL,
[GUID] [nvarchar](255) NULL,
[Inserted] [smalldatetime] NOT NULL,
[Readers] [int] NOT NULL,
CONSTRAINT [PK_FeedItems] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[FeedItems] WITH CHECK ADD CONSTRAINT [FK_FeedItems_FeedServices] FOREIGN KEY([Service])
REFERENCES [dbo].[FeedServices] ([ID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[FeedItems] CHECK CONSTRAINT [FK_FeedItems_FeedServices]
GO
ALTER TABLE [dbo].[FeedItems] ADD CONSTRAINT [DF_FeedItems_Inserted] DEFAULT (getdate()) FOR [Inserted]
GO
二表:
USE [ICI]
GO
/****** Object: Table [dbo].[FeedItemPhrases] Script Date: 04/09/2010 15:04:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[FeedItemPhrases](
[FeedItem] [int] NOT NULL,
[Phrase] [int] NOT NULL,
[Count] [smallint] NOT NULL,
CONSTRAINT [PK_FeedItemPhrases] PRIMARY KEY CLUSTERED
(
[FeedItem] ASC,
[Phrase] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[FeedItemPhrases] WITH CHECK ADD CONSTRAINT [FK_FeedItemPhrases_FeedItems] FOREIGN KEY([FeedItem])
REFERENCES [dbo].[FeedItems] ([ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[FeedItemPhrases] CHECK CONSTRAINT [FK_FeedItemPhrases_FeedItems]
GO
ALTER TABLE [dbo].[FeedItemPhrases] WITH CHECK ADD CONSTRAINT [FK_FeedItemPhrases_Phrases] FOREIGN KEY([Phrase])
REFERENCES [dbo].[Phrases] ([ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[FeedItemPhrases] CHECK CONSTRAINT [FK_FeedItemPhrases_Phrases]
GO
多:
ALTER PROCEDURE [dbo].[usp_index_itemstring]
-- Add the parameters for the stored procedure here
@item int,
@text nvarchar(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- DECLARE a table containing all words within the text
DECLARE @tempPhrases TABLE
(
[Index] int,
[Phrase] NVARCHAR(256)
);
-- extract each word from text and store it in the temp table
WITH Pieces(pn, start, [stop]) AS
(
SELECT 1, 1, CHARINDEX(' ', @text)
UNION ALL
SELECT pn + 1, CAST([stop] + 1 AS INT), CHARINDEX(' ', @text, [stop] + 1)
FROM Pieces
WHERE [stop] > 0
)
INSERT INTO @tempPhrases
SELECT pn, SUBSTRING(@text, start, CASE WHEN [stop] > 0 THEN [stop]-start ELSE LEN(@text) END) AS s
FROM Pieces
OPTION (MAXRECURSION 0);
WITH CombinedPhrases ([Phrase]) AS
(
-- SELECT ALL 2-WORD COMBINATIONS
SELECT w1.[Phrase] + ' ' + w2.[Phrase]
FROM @tempPhrases w1
JOIN @tempPhrases w2 ON w1.[Index] + 1 = w2.[Index]
UNION ALL -- SELECT ALL 3-WORD COMBINATIONS
SELECT w1.[Phrase] + ' ' + w2.[Phrase] + ' ' + w3.[Phrase]
FROM @tempPhrases w1
JOIN @tempPhrases w2 ON w1.[Index] + 1 = w2.[Index]
JOIN @tempPhrases w3 ON w1.[Index] + 2 = w3.[Index]
UNION ALL -- SELECT ALL 4-WORD COMBINATIONS
SELECT w1.[Phrase] + ' ' + w2.[Phrase] + ' ' + w3.[Phrase] + ' ' + w4.[Phrase]
FROM @tempPhrases w1
JOIN @tempPhrases w2 ON w1.[Index] + 1 = w2.[Index]
JOIN @tempPhrases w3 ON w1.[Index] + 2 = w3.[Index]
JOIN @tempPhrases w4 ON w1.[Index] + 3 = w4.[Index]
)
-- ONLY INSERT THE NEW PHRASES IN THE Phrase TABLE
INSERT INTO @tempPhrases
SELECT 0, [Phrase] FROM CombinedPhrases
-- DELETE PHRASES WHICH ARE EXCLUDED
DELETE FROM @tempPhrases
WHERE [Phrase] IN
(
SELECT [Text] FROM Phrases p
JOIN ExcludedPhrases ex
ON ex.ID = p.ID
);
MERGE INTO Phrases p
USING
(
SELECT DISTINCT Phrase FROM @tempPhrases
) t
ON p.[Text] = t.Phrase
WHEN NOT MATCHED THEN
INSERT VALUES (t.Phrase);
-- Finally create relations between the phrases and feeditem,
MERGE INTO FeedItemPhrases p
USING
(
SELECT @item as [Item], MIN(p.[ID]) as Phrase, COUNT(t.[Phrase]) as [Count]
FROM Phrases p WITH (NOLOCK)
JOIN @tempPhrases t ON p.[Text] = t.[Phrase]
GROUP BY t.[Phrase]
) t
ON p.FeedItem = t.Item
AND p.Phrase = t.Phrase
WHEN MATCHED THEN
UPDATE SET p.[Count] = t.[Count]
WHEN NOT MATCHED THEN
INSERT VALUES (t.[Item], t.Phrase, t.[Count]);
END
以及更多:
ALTER Function [dbo].[RemoveNonAlphaCharacters](@Temp NVarChar(max))
Returns NVarChar(max)
AS
Begin
SELECT @Temp = REPLACE (@Temp, '%20', ' ');
While PatIndex('%[^a-z ]%', @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex('%[^a-z ]%', @Temp), 1, '')
Return @TEmp
End
发表表格定义和触发器,你缓慢的触发器锁定/阻止你。如果没有这些信息,就不可能提供很多帮助 – 2010-04-09 12:43:25
触发器中的所有处理都在'dbo.RemoveNonAlphaCharacters()'和'dbo.usp_index_itemstring()'中完成,您是否也可以发布该代码? – 2010-04-09 13:57:59