优化SQL查询以避免哈希匹配(聚合)

gre*_*egs 9 sql sql-server performance

我有一个SQL查询需要7分钟+返回结果.我正在尝试尽可能地优化,并且执行计划在Hash Match(Aggregate)上丢失了82%的时间.我做了一些搜索,看起来像使用"EXISTS"将有助于解决,但我还没有想出查询的语法,使其工作.这是查询:

select dbo.Server.Name,
                dbo.DiskSpace.Drive,
                AVG(dbo.DiskSpace.FreeSpace) as 'Free Disk Space',
                AVG(dbo.Processor.PercentUsed) as 'CPU % Used',
                AVG(dbo.Memory.PercentUtilized) as '% Mem Used'

                from Server
                join dbo.DiskSpace on dbo.Server.ID=DiskSpace.ServerID
                join dbo.Processor on dbo.Server.ID=Processor.ServerID
                join dbo.Memory on dbo.Server.ID=dbo.Memory.ServerID

                where
                dbo.Processor.ProcessorNum='_Total' 
                    and dbo.Processor.Datetm>DATEADD(DAY,-(1),(CONVERT (date, GETDATE()))) 
                    and (      dbo.Server.Name='qp-ratking' 
                            or dbo.Server.Name='qp-hyper2012' 
                            or dbo.Server.Name='qp-hyped' 
                            or dbo.Server.Name='qp-lichking')
                Group By dbo.server.name, Dbo.DiskSpace.Drive
                Order By Dbo.Server.Name, dbo.DiskSpace.Drive;
Run Code Online (Sandbox Code Playgroud)

如何使用EXISTS减少/消除连接?或者,如果有更好的优化方法,我也会这样做.谢谢

gre*_*egs 5

一个同事打破了查询,并以较小的块的形式提取数据,因此连接返回的数据处理的次数不多.它将其减少到不到1秒的回报.新查询:

WITH tempDiskSpace AS
(
SELECT dbo.Server.Name
      ,dbo.DiskSpace.Drive
      ,AVG(dbo.DiskSpace.FreeSpace) AS 'Free Disk Space'

FROM dbo.DiskSpace
      LEFT JOIN dbo.Server ON dbo.DiskSpace.ServerID=Server.ID

WHERE dbo.DiskSpace.Datetm>DATEADD(DAY,-(1),(CONVERT (date, GETDATE())))
AND (dbo.Server.Name='qp-ratking'
      OR dbo.Server.Name='qp-hyper2012'
      OR dbo.Server.Name='qp-hyped'
      OR dbo.Server.Name='qp-lichking')

GROUP BY Name, Drive
)
,tempProcessor
AS
(
SELECT dbo.Server.Name
      ,AVG(dbo.Processor.PercentUsed) AS 'CPU % Used'

FROM dbo.Processor
      LEFT JOIN dbo.Server ON dbo.Processor.ServerID=Server.ID

WHERE dbo.Processor.Datetm>DATEADD(DAY,-(1),(CONVERT (date, GETDATE())))
AND dbo.Processor.ProcessorNum='_Total'
AND (dbo.Server.Name='qp-ratking'
      OR dbo.Server.Name='qp-hyper2012'
      OR dbo.Server.Name='qp-hyped'
      OR dbo.Server.Name='qp-lichking')

GROUP BY Name
)
,tempMemory
AS
(
SELECT dbo.Server.Name
      ,AVG(dbo.Memory.PercentUtilized) as '% Mem Used'

FROM dbo.Memory
      LEFT JOIN dbo.Server ON dbo.Memory.ServerID=Server.ID

WHERE dbo.Memory.Datetm>DATEADD(DAY,-(1),(CONVERT (date, GETDATE())))
AND (dbo.Server.Name='qp-ratking'
      OR dbo.Server.Name='qp-hyper2012'
      OR dbo.Server.Name='qp-hyped'
      OR dbo.Server.Name='qp-lichking')

GROUP BY Name
)

SELECT tempDiskSpace.Name, tempDiskSpace.Drive, tempDiskSpace.[Free Disk Space], tempProcessor.[CPU % Used], tempMemory.[% Mem Used]
FROM tempDiskSpace
LEFT JOIN tempProcessor ON tempDiskSpace.Name=tempProcessor.Name
LEFT JOIN tempMemory ON tempDiskSpace.Name=tempMemory.Name
ORDER BY Name, Drive;
Run Code Online (Sandbox Code Playgroud)

感谢所有的建议.


Gor*_*off 2

我将从检查索引开始。连接中使用的所有键都定义为吗primary keys?或者他们至少有索引吗?

然后,关于Processor和 的附加索引Server可能会有所帮助:

create index idx_Processor_ProcessorNum_Datetm_ServerId on ProcessorNum(ProcessorNum, Datetm, ServerId);
create index idx_Server_Name_ServerId on Server(Name, ServerId)
Run Code Online (Sandbox Code Playgroud)