开发者

Need help optimizing this tSQL Query

I'm definitely not a DBA and unfortunately we don't have a DBA to consult within at our company. I was wondering if someone could give me a recommendation on how to improve this query, either by changing the query itself or adding indexes to the database.

Looking at the execution plan of the query it seems like the outer joins are killing the query. This query only returns 350k results, but it takes almost 30 seconds to complete. I don't know much about DB's, but I don't think this is good? Perhaps I'm wrong?

Any suggestions would be greatly appreciated. Thanks in advance.

As a side note this is obviously being create by an ORM and not me directly. We are using 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].[Port开发者_如何学PythonFast] 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-TO-SQL Query:

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
             };


As a rule (and this is very general), you want an index on:

  • JOIN fields (both sides)
  • Common WHERE filter fields
  • Possibly fields you aggregate

For this query, start with checking your JOIN criteria. Any one of those missing will force a table scan which is a big hit.


Looking at the execution plan of the query it seems like the outer joins are killing the query. This query only returns 350k results, but it takes almost 30 seconds to complete. I don't know much about DB's, but I don't think this is good? Perhaps I'm wrong?

A man has got to do waht a mana has got to do.

The joins may kill you, but when you need them YOU NEED THEM. Some tasks take long.

  • Make sure you ahve all indices you need.
  • Make sure your sql server is not a sad joke hardware wise. All you can do.

I woudl bet someone has no clue about SQL and needs to be enlighted to the power of indices.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜