【发布时间】:2012-12-25 20:09:18
【问题描述】:
我有一个包含很多行(最多几百万行)的 SQL 表“文档”。
当我执行 Select-Statement 时,大约需要 0.5 秒。 但是当我使用相同的 WHERE 子句执行更新时,大约需要 20 到 50 秒,具体取决于受影响的行数。
这是我的数据。
//选择
SELECT * FROM Document
WHERE (State=20 OR State=23) AND
LetterClosed IS NOT NULL AND
TYPE=0 AND
SendLetter=1
//更新
UPDATE Document set State=32
WHERE (State=20 OR State=23) AND
LetterClosed IS NOT NULL AND
TYPE=0 AND
SendLetter=1
OR-Mapper 在内部按如下方式将此更新语句发送到数据库:
exec sp_executesql N'Update
Document
SET
State=@p4
WHERE
(
(
(
(Document.State = @p0 OR Document.State = @p1)
AND Document.LetterClosed IS NOT NULL
)
AND Document.Type = @p2
)
AND Document.SendLetter = @p3
)'
,N'@p0 int,@p1 int,@p2 int,@p3 bit,@p4 int',@p0=20,@p1=23,@p2=0,@p3=1,@p4=32
问题是,我在 30 秒后从我的 LightSpeed(C# 中的数据库 OR-Mapper)收到超时异常。
有人可以帮我吗?
编辑:
这是我们由 SQL-Server 自动创建的索引:
CREATE NONCLUSTERED INDEX [_dta_index_Document_9_133575514__K42_1_2_3_4_5_6_7_8_9_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_] ON [Document]
(
[State] ASC
)
INCLUDE (
[Id],[DocumentId],[SendLetter],[SendFax],[Archive],[Crm],[Validation],[CreationDate],[PageCount],
[InformationLetter],[TermsOfDelivery],[DeliveryTypeNo],[SeparateDelivery],[FormName],[FormDescription],[TemplateFileName],[RecipientType],
[HealthInsuranceNo],[FamilyHealthInsuranceNo],[PensionInsuranceNo],[EmployerCompanyNo],[RecipientName1],[RecipientName2],[RecipientName3],
[RecipientStreet],[RecipientCountryCode],[RecipientZipCode],[RecipientCity],[RecipientFaxNo],[AuthorId],
[AuthorName],[AuthorEmailAddress],[CostcenterDepartment],[CostcenterDescription],[MandatorNo],[MandatorName],[ControllerId],
[ControllerName],[EditorId],[EditorName],[StateFax],[Editable],[LetterClosedDate],[JobId],[DeliveryId],[DocumentIdExternal],[JobGroupIdExternal],
[GcosyInformed]) WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
go
CREATE NONCLUSTERED INDEX [_dta_index_Document_9_133575514__K2_1_46] ON [Document]
(
[DocumentId] ASC
)
INCLUDE ( [Id],
[JobId]) WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
go
CREATE NONCLUSTERED INDEX [_dta_index_Document_9_133575514__K46_K2] ON [Document]
(
[JobId] ASC,
[DocumentId] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
go
CREATE NONCLUSTERED INDEX [Document_State_Id] ON [Document]
(
[State] ASC,
[Id] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
go
CREATE NONCLUSTERED INDEX [Document_State_CreationDate] ON [Document]
(
[State] ASC,
[CreationDate] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
go
编辑 2: 现在我有一个图形执行计划: 执行计划:https://skydrive.live.com/redir?resid=597F6CF1AB696567!444&authkey=!ABq72SAWXOoAXfI
此 SQL 更新执行大约需要 35 秒。通常这个更新只需要 0,3 秒。似乎另一个进程阻止了这个。我看到其他一些选择在此更新中间开始并等到更新完成,直到他们在那里完成选择执行。
所以看起来索引本身是正确的(通常是 0,3 秒执行)。 所有选择(来自 java/jtds、php、.net)都是隔离级别读取提交的(默认)。它会帮助我在这里将所有选择更改为未提交的读取以避免在索引更新期间出现这种阻塞吗?
谢谢 托比
【问题讨论】:
-
SELECT返回了多少行?您使用的是什么 DBMS? (我猜来自sp_executesql的SQL-Server)你能显示CREATE TABLE语句(和现有索引)吗?可以添加执行计划吗? -
我们使用的是 MSSQL-Server 2005。我将尝试发布执行计划和创建语句。
-
还包括该表上的任何索引,您需要这样做以获得准确的答案,它可能是索引太多或太少,或者您可能只需要稍微改变一个。当您在 SSMS 中获得执行计划时,它甚至可能会建议一个可以加快执行计划的索引。
-
如果从应用程序和 SSMS 运行查询,执行时间是否相同?
-
通常人们会附上带有计划的屏幕截图,但它不适用于大计划。
标签: sql sql-server select timeout lightspeed