2011-07-21 74 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