一个非常简单的查询上的嵌套循环性能问题

时间:2020-07-06 10:35:46

标签: sql-server tsql

我有一个非常简单的表和一个非常简单的INNER JOIN查询以及大量的行。

IF OBJECT_ID('tempdb..#blackIPAndMACs') IS NOT NULL
    DROP TABLE #blackIPAndMACs
       
CREATE TABLE #blackIPAndMACs
(
       ResourceID     dsidentifier,
       MACAddress     VARCHAR(500),
       IPAddress      VARCHAR(50)
)

CREATE INDEX #blackIPAndMACs_idx1 ON #blackIPAndMACs(MACAddress)
CREATE INDEX #blackIPAndMACs_idx2 ON #blackIPAndMACs(IPAddress)
CREATE INDEX #blackIPAndMACs_idx3 ON #blackIPAndMACs(MACAddress, IPAddress)
CREATE INDEX #blackIPAndMACs_idx4 ON #blackIPAndMACs(ResourceID)

在此表中填充了2.514.000行之后,我试图查找从相似IP或MAC访问的所有ResourceID:

SELECT b1.*,
       b2.*
FROM   #blackIPAndMACs b1 with(NOLOCK, INDEX=#blackIPAndMACs_idx3) 
       INNER JOIN #blackIPAndMACs b2 with(NOLOCK, INDEX=#blackIPAndMACs_idx3)
            ON  (
                    b1.MACAddress = b2.MACAddress
                    OR b1.IPAddress = b2.IPAddress
                )    
WHERE  1 = 1

因此,此查询将无限执行(可能)。我们的服务器确实功能强大。我想我无法透露这些信息,但是我只能说,服务器的RAM数量高达数百GB。

enter image description here

我应该使用哪种优化来加快查询的执行速度?

更新1:

好的,我删除了OR并将SELECT更改为count (b1.ResourceID),但这并不能解决问题。甚至这种简单的查询执行时间也太长:

SELECT count (b1.ResourceID)
FROM   #blackIPAndMACs b1 with(NOLOCK) 
       INNER JOIN #blackIPAndMACs b2 with(NOLOCK)              
                    b1.MACAddress = b2.MACAddress
WHERE  1 = 1
AND b1.ResourceID != b2.ResourceID

enter image description here

1 个答案:

答案 0 :(得分:2)

作为一种习惯,即使您需要一堆字段,我也尽量避免使用select *。话虽如此,我的方法将是这样的:

SELECT
          b1.ResourceID
        , b2.MACAddress
        , b2.IPAddress
        , b3.MACAddress
        , b3.IPAddress
FROM      #blackIPAndMACs AS b1
LEFT JOIN #blackIPAndMACs AS b2 ON b1.MACAddress = b2.MACAddress
LEFT JOIN #blackIPAndMACs AS b3 ON b1.IPAddress = b2.IPAddress;

使用更有效的查询计划:

enter image description here