2014-07-18 2 views
5

결과를 반환하는 데 7 분이 걸리는 SQL 쿼리가 있습니다. 나는 가능한 한 많이 최적화하려고 노력하고 있으며 실행 계획은 해시 경기 (집계)에서 82 %의 시간을 잃어버린다. 일부 검색을 수행하고 "EXISTS"를 사용하여 해결하는 데 도움이되는 것처럼 보이지만 작동하도록 쿼리의 구문을 파악하지 못했습니다. 다음은 쿼리입니다.해시 일치 (집계)를 피하기 위해 SQL 쿼리 최적화

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; 

EXISTS를 사용하여 조인을 줄이거 나 제거하려면 어떻게합니까? 또는 최적화 할 수있는 더 좋은 방법이 있다면, 나는 그것에 대해서도 마찬가지입니다. 감사합니다

답변

2

색인을 확인하여 시작할 것입니다. 조인에 사용 된 모든 키가 primary keys으로 정의되어 있습니까? 아니면 적어도 색인을 가지고 있습니까?

그런 다음, ProcessorServer에 추가 인덱스가 도움이 될 수 있습니다 :

create index idx_Processor_ProcessorNum_Datetm_ServerId on ProcessorNum(ProcessorNum, Datetm, ServerId); 
create index idx_Server_Name_ServerId on Server(Name, ServerId) 
2

문 합리적으로 구조화 된 모양과 최적화를위한 거대한 범위가 표시되지는 requisits가 당 해결 된 같은

    제공
  1. 인덱스 조각화를 확인하고 모든 인덱스가 유지되는지 확인하십시오.
  2. 통계가 최신인지 확인하십시오.
  3. 더티 준비가 가능하면 테이블에 WITH (NOLOCK)을 적용하는 것이 좋습니다.
  4. 쿼리에서 변수 선언을 허용하면 다음과 같이 Filter 문에서 DATEADD를 이동하면 유용 할 수 있습니다. 이 도움이

희망.

-- Assuming Variables can be declared see the script below. 
-- I made a few changes per my coding standard only to help me read better. 

DECLARE의 @dt_Yesterdate 날짜 SET @dt_Yesterdate = DATEADD (DAY - (1) 변환 (DATE, GETDATE는()))

SELECT s.Name, 
     ds.Drive, 
     AVG(ds.FreeSpace) AS 'Free Disk Space', 
     AVG(P.PercentUsed) AS 'CPU % Used', 
     AVG(m.PercentUtilized) AS '% Mem Used' 
FROM Server s 
    JOIN dbo.DiskSpace AS ds 
     ON s.ID = ds.ServerID 
    JOIN dbo.Processor AS p 
     ON s.ID = p.ServerID 
    JOIN dbo.Memory AS m 
     ON s.ID = m.ServerID 
WHERE P.ProcessorNum = '_Total' 
    AND P.Datetm > @dt_Yesterdate 
    AND s.Name IN ('qp-ratking', 'qp-hyper2012', 'qp-hyped','qp-lichking') 
GROUP BY s.name, ds.Drive 
ORDER BY s.Name, ds.Drive; 
3

공동 -worker는 쿼리를 중단하고 더 작은 청크로 데이터를 추출 했으므로 조인에 의해 반환 된 데이터의 처리량이 그다지 많지 않았습니다. 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; 

모든 제안 주셔서 감사합니다.

1

적어도 모든 OR 절을 없애는 것으로 시작합니다.

AND (dbo.Server.Name='qp-ratking' 
     OR dbo.Server.Name='qp-hyper2012' 
     OR dbo.Server.Name='qp-hyped' 
     OR dbo.Server.Name='qp-lichking') 

내가 생각 열팽창 계수에 모든 것을 변환하는 방법에 대한 확실하지 않다

AND dbo.Server.Name in ('qp-ratking','qp-hyper2012','qp-hyped','qp-lichking') 

로 교체합니다. CTE를 인덱싱 할 수는 없으며 CTE가 일반적인 쿼리보다 우수한 경우를 찾아야합니다. 위에서 언급 한 OR의 과도한 사용과는 별도로 초기 쿼리가 잘 형성되어있는 것처럼 보였으므로 다음 인덱스를 살펴볼 것입니다.