簡體   English   中英

SQL Update非常慢(大約20-50秒),Select只需不到1秒

[英]SQL Update is really slow (about 20-50sec), Select takes less than 1 second

我有一個SQL Tabe“文檔”,其中包含很多行(最多幾百萬)。

當我執行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在內部將此update-statement發送到數據庫:

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

問題是,我在LightSpeed(c#中的數據庫OR-Mapper)30秒后得到Timeout-Exception。

誰能在這幫助我?

編輯:

這是我們由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

執行計划索引更新詳細信息: https//skydrive.live.com/?cid = 597f6cf1ab696567&id = 597F6CF1AB696567%21445&sff = 1&authkey =!ADDPWvxB2JLLvWo

此SQL-Update大約需要35秒才能執行。 通常此更新僅需0.3秒。 似乎另一個進程阻止了這個。 我看到了一些其他選擇,它們在此更新過程中開始,一直等到更新完成,直到完成select-execution。

所以看起來索引本身是正確的(通常是0.3秒執行)。 所有選擇(來自java / jtds,php,.net)都是隔離級別讀取提交(默認)。 這會幫助我在這里更改所有選擇讀取未提交以避免在索引更新期間阻止此操作嗎?

謝謝托比

沒有執行計划,我們只能猜測會發生什么。

我會從:

  1. 檢查document表有多少索引(但很難相信更新索引需要這么多時間)。
  2. 檢查是否在更新時執行了任何觸發器。

所有這些都應該在執行計划中可見。

另一個原因可能是SQL引擎有一個用於SELECT查詢的執行計划,另一個用於UPDATE查詢...

UPDATE

在查看索引之后。

在我看來,索引_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_是完全錯誤的。

它包含許多可能使更新變慢的列。

嘗試刪除它或用state列上的CLUSTERED索引替換它。 CLUSTERED索引*包括*(可直接訪問)所有記錄列而無需額外讀取。

可能它應該與以state列開始的其他索引之一結合 - 我假設state只有幾個值。

不幸的是,我無法以文本格式解釋執行計划。

可能你在表Document上有索引。 索引使選擇更快但更慢的更新/插入/刪除操作。

嘗試刪除不必要的索引

我曾經在SQL Server 2008和SQL Server 2014鏈接服務器上遇到此問題。 對我來說, 解決方法是將“選擇”結果存儲到臨時表中,並使用它來執行更新,而不是立即執行復雜查詢和更新。

在你的情況下,這將是:

--Select

SELECT * FROM Document
into #temp 
WHERE (State=20 OR State=23) AND 
LetterClosed IS NOT NULL AND 
TYPE=0 AND
SendLetter=1

--Update

UPDATE Document set State=32 
from #temp
WHERE #temp.id = Document.id 
--assuming that id is your PK

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM