2011-07-21 117 views
0

我絕對不是DBA,很遺憾,我們沒有DBA在我們公司內部進行諮詢。我想知道是否有人可以通過改變查詢本身或向數據庫添加索引,向我推薦如何改進此查詢。需要幫助優化這個tSQL查詢

看看查詢的執行計劃,它看起來像外部連接正在查殺查詢。此查詢只返回350k結果,但完成需要將近30秒。我對DB的瞭解不多,但我認爲這不好?也許我錯了?

任何建議將不勝感激。提前致謝。

作爲一個附註,這顯然是由ORM創建的,而不是直接創建的。我們正在使用Linq-to-SQL。

SELECT 
    [t12].[value] AS [DiscoveryEnabled], 
    [t12].[value2] AS [isConnected], 
    [t12].[Interface], 
    [t12].[Description] AS [InterfaceDescription], 
    [t12].[value3] AS [Duplex], 
    [t12].[value4] AS [IsEnabled], 
    [t12].[value5] AS [Host], 
    [t12].[value6] AS [HostIP], 
    [t12].[value7] AS [MAC], 
    [t12].[value8] AS [MACadded], 
    [t12].[value9] AS [PortFast], 
    [t12].[value10] AS [PortSecurity], 
    [t12].[value11] AS [ShortHost], 
    [t12].[value12] AS [SNMPlink], 
    [t12].[value13] AS [Speed], 
    [t12].[value14] AS [InterfaceStatus], 
    [t12].[InterfaceType], 
    [t12].[value15] AS [IsUserPort], 
    [t12].[value16] AS [VLAN], 
    [t12].[value17] AS [Code], 
    [t12].[Description2] AS [Description], 
    [t12].[Host] AS [DeviceName], 
    [t12].[NET_OUID], 
    [t12].[DisplayName] AS [Net_OU], 
    [t12].[Enclave] 
FROM (
    SELECT 
     [t1].[DiscoveryEnabled] AS [value], 
     [t1].[IsConnected] AS [value2], 
     [t0].[Interface], 
     [t0].[Description], 
     [t2].[Duplex] AS [value3], 
     [t0].[IsEnabled] AS [value4], 
     [t3].[Host] AS [value5], 
     [t6].[Address] AS [value6], 
     [t3].[MAC] AS [value7], 
     [t3].[MACadded] AS [value8], 
     [t2].[PortFast] AS [value9], 
     [t2].[PortSecurity] AS [value10], 
     [t4].[Host] AS [value11], 
     [t0].[SNMPlink] AS [value12], 
     [t2].[Speed] AS [value13], 
     [t2].[InterfaceStatus] AS [value14], 
     [t8].[InterfaceType], 
     [t0].[IsUserPort] AS [value15], 
     [t2].[VLAN] AS [value16], 
     [t9].[Code] AS [value17], 
     [t9].[Description] AS [Description2], 
     [t7].[Host], [t7].[NET_OUID], 
     [t10].[DisplayName], 
     [t11].[Enclave], 
     [t7].[Decommissioned] 
    FROM [dbo].[IDB_Interface] AS [t0] 
     LEFT OUTER JOIN [dbo].[IDB_InterfaceLayer2] AS [t1] ON [t0].[IDB_Interface_ID] = [t1].[IDB_Interface_ID] 
     LEFT OUTER JOIN [dbo].[IDB_LANinterface] AS [t2] ON [t1].[IDB_InterfaceLayer2_ID] = [t2].[IDB_InterfaceLayer2_ID] 
     LEFT OUTER JOIN [dbo].[IDB_Host] AS [t3] ON [t2].[IDB_LANinterface_ID] = [t3].[IDB_LANinterface_ID] 
     LEFT OUTER JOIN [dbo].[IDB_Infrastructure] AS [t4] ON [t0].[IDB_Interface_ID] = [t4].[IDB_Interface_ID] 
     LEFT OUTER JOIN [dbo].[IDB_AddressMapIPv4] AS [t5] ON [t3].[IDB_AddressMapIPv4_ID] = ([t5].[IDB_AddressMapIPv4_ID]) 
     LEFT OUTER JOIN [dbo].[IDB_AddressIPv4] AS [t6] ON [t5].[IDB_AddressIPv4_ID] = [t6].[IDB_AddressIPv4_ID] 
     INNER JOIN [dbo].[ART_Asset] AS [t7] ON [t7].[ART_Asset_ID] = [t0].[ART_Asset_ID] 
     LEFT OUTER JOIN [dbo].[NSD_InterfaceType] AS [t8] ON [t8].[NSD_InterfaceTypeID] = [t0].[NSD_InterfaceTypeID] 
     INNER JOIN [dbo].[NSD_InterfaceCode] AS [t9] ON [t9].[NSD_InterfaceCodeID] = [t0].[NSD_InterfaceCodeID] 
     INNER JOIN [dbo].[NET_OU] AS [t10] ON [t10].[NET_OUID] = [t7].[NET_OUID] 
     INNER JOIN [dbo].[NET_Enclave] AS [t11] ON [t11].[NET_EnclaveID] = [t10].[NET_EnclaveID] 
    ) AS [t12] 
WHERE ([t12].[Enclave] = 'USMC') AND (NOT ([t12].[Decommissioned] = 1)) 

LINQ到SQL查詢:

return from t in db.IDB_Interfaces 
      join v in db.IDB_InterfaceLayer3s on t.IDB_Interface_ID equals v.IDB_Interface_ID 
      join u in db.ART_Assets on t.ART_Asset_ID equals u.ART_Asset_ID 
      join c in db.NET_OUs on u.NET_OUID equals c.NET_OUID 
      join w in 
       (from d in db.IDB_InterfaceIPv4s 
       select new { d.IDB_InterfaceIPv4_ID, d.IDB_InterfaceLayer3_ID, d.IDB_AddressMapIPv4_ID, d.IDB_AddressMapIPv4.IDB_AddressIPv4.Address }) 
      on v.IDB_InterfaceLayer3_ID equals w.IDB_InterfaceLayer3_ID 
      join h in db.NET_Enclaves on c.NET_EnclaveID equals h.NET_EnclaveID into enclaveLeftJoin 
      from i in enclaveLeftJoin.DefaultIfEmpty() 
      join m in 
       (from z in db.IDB_StandbyIPv4s 
       select new 
       { 
        z.IDB_InterfaceIPv4_ID, 
        z.IDB_AddressMapIPv4_ID, 
        z.IDB_AddressMapIPv4.IDB_AddressIPv4.Address, 
        z.Preempt, 
        z.Priority 
       }) 
      on w.IDB_InterfaceIPv4_ID equals m.IDB_InterfaceIPv4_ID into standbyLeftJoin 
      from k in standbyLeftJoin.DefaultIfEmpty() 
      where t.ART_Asset.Decommissioned == false 
      select new NetIDBGridDataResults 
      { 
       DeviceName = u.Host, 
       Host = u.Host, 
       Interface = t.Interface, 
       IPAddress = w.Address, 
       ACLIn = v.InboundACL, 
       ACLOut = v.OutboundACL, 
       VirtualAddress = k.Address, 
       VirtualPriority = k.Priority, 
       VirtualPreempt = k.Preempt, 
       InterfaceDescription = t.Description, 
       Enclave = i.Enclave 
      }; 
+0

您需要告訴我們關於表結構和已經存在的索引。 – JNK

+1

當你說30秒返回數據時,數據在哪裏?如果你在SSMS中運行它,那麼只需要30秒,UI就可以顯示數據,而不必提及通過網絡的時間,如果你實際上不在服務器上。 –

+3

請以文本格式**發佈執行計劃**。運行'SET SHOWPLAN_TEXT ON GO SELECT ...' – Quassnoi

回答

1

作爲一項規則(這是很普遍),你想在索引:

  • JOIN場(兩側)
  • 常見WHERE過濾器領域
  • 可能字段您彙總

對於此查詢,從檢查您的JOIN條件開始。任何一個失蹤的人都會強制進行桌面掃描,這是一個很大的打擊。

0

望着查詢的執行計劃,它似乎像外部聯接殺死查詢。 該查詢只返回350k結果,但完成需要將近30秒。我不知道 關於DB的很多,但我不認爲這是好的?也許我錯了?

一個男人必須做一個法力需要做的事情。

連接可能會殺了你,但是當你需要它們時,你需要它們。有些任務需要很長時間

  • 請確保您擁有所有您需要的指數。
  • 確保你的sql服務器不是一個悲傷的笑話硬件明智。 你只能做。

我可以賭一個人對SQL沒有任何線索,需要指出索引的力量。

+0

每個表都有PK/FK。但是,我不知道指數。我在這裏問的原因。 –

+0

那麼,然後RTFM。 CREATE INDEX是你的朋友。你用無效的表掃描來殺死數據庫。並且,不,抱歉,Stackoverflow不會阻止您閱讀數據庫文章的介紹。 – TomTom