2014-12-04 43 views
0

這兩個查詢爲什麼會有這樣的差異?針對特定鍵值的慢SQL SELECT

這個查詢花費約51秒來完成:

SELECT TOP 1000 * 
FROM [PHONER].[dbo].[V_PhonerSubjects] 
WHERE ProjectID = 137; 

然而,這種查詢採用約1秒至完成:

SELECT TOP 1000 * 
FROM [PHONER].[dbo].[V_PhonerSubjects] 
WHERE ProjectID = 107; 

注意:唯一的區別是關鍵的值。

兩者共有超過1000條記錄。項目107有26000條記錄,項目137有4500條記錄。

ProjectID是索引主鍵。

我注意到,第二個查詢在1秒內​​完成並將所有行發送到結果窗口。第一個查詢開始在大約3秒後發送行,並在大約51秒後完成。

這是查看V_PhonerSubjects的SQL:

SELECT   
    dbo.PhonerEmner.PhonerEmID AS SubjectID, dbo.PhonerEmner.FK_ProID AS ProjectID, 
    dbo.PhonerProjekt.PhonerTitel AS ProjectName, dbo.Medlemsdata.Vennenr AS FriendNo, 
    dbo.Medlemsdata.OpretteDato AS CreatedDate, dbo.Medlemsdata.OpretteID AS CreatedID, 
    dbo.Bruger.Intialer AS CreatedBy, dbo.Medlemsdata.ÆndretDato AS ChangedDate, 
    dbo.Medlemsdata.ÆndretID AS ChangedID, 
    Bruger_3.Intialer AS ChangedBy, 
    ISNULL(dbo.Medlemsdata.Organisation, N'') + N' ' + ISNULL(dbo.Medlemsdata.Fornavn, N'') + N' ' + ISNULL(dbo.Medlemsdata.Efternavn, N'') AS Name, 
    dbo.MedlemsAdresse.AdrID AS AddressID, dbo.MedlemsAdresse.Adresse AS Address1, 
    dbo.MedlemsAdresse.Adresse2 AS Address2, dbo.MedlemsAdresse.Postnr AS ZIP, 
    dbo.Postnumre.[By] AS City, dbo.Medlemsdata.CPRnr AS CPRno, 
    dbo.Medlemsdata.Køn AS Gender, dbo.Medlemsdata.Telefon AS Phone01, 
    dbo.Medlemsdata.TlfNote1 AS Phone02Type, dbo.Medlemsdata.Tlf1 AS Phone02, 
    dbo.Medlemsdata.TlfNote2 AS Phone03Type, dbo.Medlemsdata.Tlf2 AS Phone03, 
    dbo.Medlemsdata.TlfNote3 AS Phone04Type, 
    dbo.Medlemsdata.Tlf3 AS Phone04, dbo.Medlemsdata.TlfSMS AS PhoneMobile, 
    dbo.Medlemsdata.[E-mail] AS Email, dbo.Medlemsdata.SPFelt1 AS SPField01, 
    dbo.Medlemsdata.SPFelt2 AS SPField02, dbo.Medlemsdata.SPFelt3 AS SPField03, 
    dbo.Medlemsdata.SPFelt4 AS SPField04, dbo.Medlemsdata.SPFelt5 AS SPField05, 
    dbo.Medlemsdata.SPFelt6 AS SPField06, dbo.Medlemsdata.SPFelt7 AS SPField07, 
    dbo.Medlemsdata.SPFelt8 AS SPField08, dbo.Medlemsdata.SPFelt9 AS SPField09, 
    dbo.Medlemsdata.SPFelt10 AS SPField10, dbo.Medlemsdata.SPFelt11 AS SPField11, 
    dbo.Medlemsdata.SPFelt12 AS SPField12, dbo.Medlemsdata.SPFelt13 AS SPField13, 
    dbo.Medlemsdata.SPFelt14 AS SPField14, dbo.PhonerEmner.SidsteKontakt AS LastContact, 
    dbo.PhonerEmner.AntalKontakt AS ContactTimes, dbo.PhonerEmner.KontaktDage AS ContactDays, 
    dbo.PhonerEmner.KontaktEfter AS ContactAfter, 
    dbo.PhonerEmner.PhonerIgen AS ContactAfterPhonerID, 
    Bruger_1.Navn AS ContactAfterPhonerName, dbo.PhonerEmner.PhonerNote, 
    dbo.PhonerEmner.Stemning AS Mood, dbo.PhonerEmner.Status, 
    dbo.PhonerEmner.PhonerAft AS LastPhonerID, Bruger_2.Navn AS LastPhonerName, 
    dbo.PhonerEmner.SlutNote AS EndNote, dbo.PhonerEmner.SlutDato AS EndDate, 
    dbo.PhonerImport.PhonerImportID AS ImportID, dbo.PhonerImportData.Status AS ImportStatus, 
    dbo.PhonerImport.ImportFileName, dbo.PhonerImport.ImportTime, 
    dbo.PhonerProjekt.SvarerIkkeTid 
FROM    
    dbo.Bruger AS Bruger_1 
RIGHT OUTER JOIN 
    dbo.PhonerProjekt 
RIGHT OUTER JOIN 
    dbo.PhonerEmner ON dbo.PhonerProjekt.PhonerProID = dbo.PhonerEmner.FK_ProID 
LEFT OUTER JOIN 
    dbo.PhonerImportData ON dbo.PhonerEmner.PhonerEmID = dbo.PhonerImportData.FK_PhonerEmID 
LEFT OUTER JOIN 
    dbo.Bruger AS Bruger_2 ON dbo.PhonerEmner.PhonerAft = Bruger_2.BrugerID ON Bruger_1.BrugerID = dbo.PhonerEmner.PhonerIgen 
LEFT OUTER JOIN 
    dbo.Bruger 
RIGHT OUTER JOIN 
    dbo.Bruger AS Bruger_3 
RIGHT OUTER JOIN 
    dbo.Medlemsdata ON Bruger_3.BrugerID = dbo.Medlemsdata.ÆndretID ON dbo.Bruger.BrugerID = dbo.Medlemsdata.OpretteID ON dbo.PhonerEmner.FK_Vennenr = dbo.Medlemsdata.Vennenr 
LEFT OUTER JOIN 
    dbo.Postnumre 
RIGHT OUTER JOIN 
    dbo.MedlemsAdresse ON dbo.Postnumre.Postnummer = dbo.MedlemsAdresse.Postnr ON dbo.Medlemsdata.FK_AdrID = dbo.MedlemsAdresse.AdrID 
LEFT OUTER JOIN 
    dbo.PhonerImport ON dbo.PhonerImportData.FK_PhonerImportID = dbo.PhonerImport.PhonerImportID 

項目107客戶端統計:

Client Execution Time 14:04:24   
Query Profile Statistics    
    Number of INSERT, DELETE and UPDATE statements 0  0.0000 
    Rows affected by INSERT, DELETE, or UPDATE statements 0  0.0000 
    Number of SELECT statements 2  2.0000 
    Rows returned by SELECT statements 1001  1001.0000 
    Number of transactions 0  0.0000 
Network Statistics   
    Number of server roundtrips 3  3.0000 
    TDS packets sent from client 3  3.0000 
    TDS packets received from server 241  241.0000 
    Bytes sent from client 340  340.0000 
    Bytes received from server 976874  976874.0000 
Time Statistics   
    Client processing time 95  95.0000 
    Total execution time 391  391.0000 
    Wait time on server replies 296  296.0000 

項目137客戶端統計:

Client Execution Time 13:58:28   
Query Profile Statistics    
    Number of INSERT, DELETE and UPDATE statements 0  0.0000 
    Rows affected by INSERT, DELETE, or UPDATE statements 0  0.0000 
    Number of SELECT statements 2  2.0000 
    Rows returned by SELECT statements 1001  1001.0000 
    Number of transactions 0  0.0000 
Network Statistics   
    Number of server roundtrips 3  3.0000 
    TDS packets sent from client 3  3.0000 
    TDS packets received from server 217  217.0000 
    Bytes sent from client 340  340.0000 
    Bytes received from server 877700  877700.0000 
Time Statistics   
    Client processing time 129596  129596.0000 
    Total execution time 130297  130297.0000 
    Wait time on server replies 701  701.0000 
+1

如果您爲兩個語句單獨提供查詢執行計劃可能會有所幫助。在SQL Management Studio中,選擇「包括實際執行計劃」圖標(或使用Ctrl + M將其切換),並在查詢完成後獲取執行計劃,該計劃將作爲標籤爲「執行計劃」的選項卡提供查詢結果窗格。這些執行計劃對於每個查詢分別是什麼樣的? – Seibar 2014-12-04 20:32:44

+2

也許過時的統計數據?在執行計劃中檢查估計的行與實際行返回 – 2014-12-04 20:35:17

+0

請發佈2查詢計劃。 – 2014-12-04 21:00:06

回答

0

鑑於少行運行速度較慢,我會懷疑數據內容,而不是架構。

如果一個數據集在大多數OUTER JOIN上找到匹配項,而另一個則不匹配,這可能會導致運行時的一些差異。加入時,一個小姐只是指數,但一個表中讀取結果。

+0

這也是我第一次懷疑。但更多的是其他方式。例如,項目107有35個關聯的導入文件,其中項目137只有3個。 – 2014-12-05 12:48:40

1

左右連接的複雜混亂以及查詢的非關聯可讀性可能會成爲問題的一部分。我可能完全錯誤,並接受。但是,我基於從各個表到所有下一級的所有層次連接標準重新構造您的查詢...每個表「JOIN」ed和「ON」條件直接作爲關聯vs混合。在這裏,你可以從層次上看到這些表格與相關的細節。我還使用ALIASES從原始文章更好的可讀性。

所以,看起來你有一些手機項目加入到PhonerEmner表中。基於這些元素,您試圖儘可能多地查找二次數據。如果它存在,很好,得到它,但不要停止,如果沒有在子級相關表中找到這樣的記錄。這樣,它們都是LEFT JOIN。如果您希望在任何給定表中都需要記錄,只需從LEFT JOIN更改爲INNER JOIN,並/或添加WHERE子句以確保找到給定的別名.ID列。

所有這一切說,我會確保該表有索引才能正確地優化通過加入..

table   index 
PhonerEmner  (FK_ProID, PhonerIgen, PhonerEmID, PhonerAft, FK_Vennenr 
PhonerProjekt (PhonerProID) 
Bruger   (BrugerID 
PhonerImportData (FK_PhonerEmID, FK_PhonerImportID 
PhonerImport  (PhonerImportID 
Medlemsdata  (Vennenr, OpretteID, ÆndretID, FK_AdrID) 
MedlemsAdresse (AdrID, Postnr) 
Postnumre  (Postnummer) 

,並與您可以創建一個新的視圖來測試針對此修訂查詢上來。

SELECT 
     PE.PhonerEmID AS SubjectID, 
     PE.FK_ProID AS ProjectID, 
     PP.PhonerTitel AS ProjectName, 
     MED.Vennenr AS FriendNo, 
     MED.OpretteDato AS CreatedDate, 
     MED.OpretteID AS CreatedID, 
     B.Intialer AS CreatedBy, 
     MED.ÆndretDato AS ChangedDate, 
     MED.ÆndretID AS ChangedID, 
     B3.Intialer AS ChangedBy, 
     ISNULL(MED.Organisation, N'') 
     + N' ' + ISNULL(MED.Fornavn, N'') 
     + N' ' + ISNULL(MED.Efternavn, N'') AS Name, 
     ADR.AdrID AS AddressID, 
     ADR.Adresse AS Address1, 
     ADR.Adresse2 AS Address2, 
     ADR.Postnr AS ZIP, 
     PST.[By] AS City, 
     MED.CPRnr AS CPRno, 
     MED.Køn AS Gender, 
     MED.Telefon AS Phone01, 
     MED.TlfNote1 AS Phone02Type, 
     MED.Tlf1 AS Phone02, 
     MED.TlfNote2 AS Phone03Type, 
     MED.Tlf2 AS Phone03, 
     MED.TlfNote3 AS Phone04Type, 
     MED.Tlf3 AS Phone04, 
     MED.TlfSMS AS PhoneMobile, 
     MED.[E-mail] AS Email, 
     MED.SPFelt1 AS SPField01, 
     MED.SPFelt2 AS SPField02, 
     MED.SPFelt3 AS SPField03, 
     MED.SPFelt4 AS SPField04, 
     MED.SPFelt5 AS SPField05, 
     MED.SPFelt6 AS SPField06, 
     MED.SPFelt7 AS SPField07, 
     MED.SPFelt8 AS SPField08, 
     MED.SPFelt9 AS SPField09, 
     MED.SPFelt10 AS SPField10, 
     MED.SPFelt11 AS SPField11, 
     MED.SPFelt12 AS SPField12, 
     MED.SPFelt13 AS SPField13, 
     MED.SPFelt14 AS SPField14, 
     PE.SidsteKontakt AS LastContact, 
     PE.AntalKontakt AS ContactTimes, 
     PE.KontaktDage AS ContactDays, 
     PE.KontaktEfter AS ContactAfter, 
     PE.PhonerIgen AS ContactAfterPhonerID, 
     B1.Navn AS ContactAfterPhonerName, 
     PE.PhonerNote, 
     PE.Stemning AS Mood, 
     PE.Status, 
     PE.PhonerAft AS LastPhonerID, 
     B2.Navn AS LastPhonerName, 
     PE.SlutNote AS EndNote, 
     PE.SlutDato AS EndDate, 
     PI.PhonerImportID AS ImportID, 
     PID.Status AS ImportStatus, 
     PI.ImportFileName, PI.ImportTime, 
     PP.SvarerIkkeTid 
    FROM 
     dbo.PhonerEmner PE 
     LEFT JOIN dbo.PhonerProjekt PP 
      ON PE.FK_ProID = PP.PhonerProID 
     LEFT JOIN dbo.Bruger B1 
      ON PE.PhonerIgen = B1.BrugerID 
     LEFT JOIN dbo.PhonerImportData PID 
      ON PE.PhonerEmID = PID.FK_PhonerEmID 
      LEFT JOIN dbo.PhonerImport PI 
       ON PID.FK_PhonerImportID = PI.PhonerImportID 
     LEFT JOIN dbo.Bruger B2 
      ON PE.PhonerAft = B2.BrugerID 
     LEFT JOIN dbo.Medlemsdata MED 
      ON PE.FK_Vennenr = MED.Vennenr 
      LEFT JOIN dbo.Bruger B 
       ON MED.OpretteID = B.BrugerID 
      LEFT JOIN dbo.Bruger B3 
       ON MED.ÆndretID = B3.BrugerID 
      LEFT JOIN dbo.MedlemsAdresse ADR 
       ON MED.FK_AdrID = ADR.AdrID 
       LEFT JOIN dbo.Postnumre PST 
        ON ADR.Postnr = PST.Postnummer 
+0

我實施了您的建議並確保上述索引已生成。根本沒有改變。可讀性低的原因是由於Microsoft SQL Management Studio的視圖設計師。 – 2014-12-05 12:51:51

+0

@JackW.Jensen,我瞭解設計師試圖爲你思考的問題。你是否以獨立視圖的形式進行操作,並從中進行查詢......或者是否創建了第二個視圖,但是是從原始視圖進行查詢。聽起來不好,但我甚至有時腦痙攣:) – DRapp 2014-12-05 13:40:16

+0

它是一種視圖,是搜索工具的基礎。搜索工具構建一個where條件並從視圖中檢索結果。 – 2014-12-05 15:44:38

0

我發現了這個問題。

我改變了連接。對我來說,不管我是以這種方式還是以另一種方式做到了這一點,但顯然它確實如此。

而不是將PhonerEmner加入PhonerEmID = PhonerEmID = FK_PhonerEmID上的PhonerImportData。我在Vennenr = FK_Vennenr加入MedlemsData到PhonerImportData。它必須與PhonerEmID不是主鍵,而只是索引有關。