2012-11-09 3 views
2

나는 다음과 같은 쿼리를 가지고 :중첩 된 선택 쿼리 최적화 느린 실행

SELECT 
    ROUND(SUM(AGLR  * BlokInsideAreaFactor), 2) AS AGLRSum, 
    ROUND(SUM(Vaarsaed * BlokInsideAreaFactor), 2) AS VaarsaedSum, 
    ROUND(SUM(Vintsaed * BlokInsideAreaFactor), 2) AS VintsaedSum, 
    ROUND(SUM(Oliefroe * BlokInsideAreaFactor), 2) AS OliefroeSum, 
    ROUND(SUM(Baelgsaed * BlokInsideAreaFactor), 2) AS BaelgsaedSum 
    .... (+ 10 more columns) 
FROM 
(
    SELECT 
     AGLR,   
     Vaarsaed,  
     Vintsaed,  
     Oliefroe,  
     Baelgsaed, 
     .... (+ 10 more columns) 
     Round((CASE WHEN bloktema.AREAL > 0 THEN 
     omraade.Geom.STIntersection(bloktema.Geom).STArea()/bloktema.AREAL ELSE 0 END), 2) 
      AS BlokInsideAreaFactor 
    FROM [CTtoolsData].dbo.BlokAfgroedeGrp blokAfgroed 
    INNER JOIN [CTtoolsTema].dbo.bloktema2012 bloktema 
     ON (bloktema.bloknr = blokAfgroed.bloknr) 
    INNER JOIN [CTtoolsTema].dbo.Area omraade 
     ON omraade.Geom.STIntersects(bloktema.GEOM) = 1 
    where omraade.Id = 296 
      AND blokAfgroed.[Year] = 2012 
) AS Q1 
내가 그것을 곱 전에 "BlokInsideAreaFactor"를 계산해야하기 때문에 내가 중첩 된 선택을했던 이유는

외부 선택의 다른 열 값.

처음 생각했을 때 "BlokInsideAreaFactor"는 행당 15 회 (열당 한 번) 대신 각 행마다 한 번만 계산되므로이 방식으로 쿼리를 최적화하는 것이 좋습니다. 문제는 쿼리가 매우 느리게 진행되는 것과 같습니다. 쿼리에는 약 4,000 개의 행을 포함하는 약 15 분이 소요됩니다. 불행히도 우리는 노후화 된 하드웨어를 가지고 있으며 SQLServer 2012 Express에서 쿼리를 실행하고 있습니다.

인덱스를 살펴본 결과 그 이상으로는 최적화 할 수 없습니다. 왜 이렇게 보이는 쿼리는 느린 속도를 내고 왜 그런 쿼리를 최적화 할 수있는 방법이 있습니까?

UPDATE : 모양을 포함

표를 다음과 같이

BlokAfgroedeGrp :

  • 열 : 아이디 (기본 키, 정체성), BlokNr, 년도, AGLR, Vaarsaed을 , Vintsaed ... 등.
  • 인덱스 : + 아이디 (기본 키, 정체성), BlokNr, 기하 구조 (구조) :

    • 열 : 아이디에 클러스터는 고유 BlokNr + 년도에

    Bloktema2012 비 클러스터 기타 (중요하지 않음)

  • 색인 : 클러스터 된 Id, Spatial on Geom, 비 고유 - ID가 + 클러스터되지 않음 BlokNr, 비 고유 - BlokNr 단독으로 클러스터되지 않음.

지역 :

  • 열 : 아이디 (기본 키, 정체성), 기하 (도형) + 기타 (중요하지 않음)
  • 인덱스 : 기하 구조
  • 에 아이디, 공간에 클러스터

인덱스에 조각화가 없는지 확인했습니다.

+1

관련된 테이블 구조는 무엇입니까? 이러한 테이블에는 어떤 종류의 인덱스가 있습니까? –

+1

"쿼리에 약 4000 개의 행이 포함 된 약 15 분이 걸립니다"- 486에서 실행 중입니까? –

+0

실행 계획을 게시 할 수 있다면 도움이 될 것입니다. – Farfarak

답변

1

저는 최근에 임시 테이블에 대해 학습 한 후에이 질문에 다시 왔습니다. 쿼리를 다음과 같이 최적화 할 수있었습니다.

DECLARE @TempTable TABLE (AGLR float,   
    Vaarsaed float,  
    Vintsaed float,  
    Oliefroe float,  
    Baelgsaed float, 
    BlokInsideAreaFactor float) 

INSERT INTO @TempTable (AGLR, Vaarsaed, Vintsaed, Oliefroe, Baelgsaed, BlokInsideAreaFactor) 

SELECT 
    AGLR,   
    Vaarsaed,  
    Vintsaed,  
    Oliefroe,  
    Baelgsaed, 
    Round((CASE WHEN bloktema.AREAL > 0 THEN 
    omraade.Geom.STIntersection(bloktema.Geom).STArea()/bloktema.AREAL ELSE 0 END), 2) 
     AS BlokInsideAreaFactor 
FROM [CTtoolsData].dbo.BlokAfgroedeGrp blokAfgroed 
INNER JOIN [CTtoolsTema].dbo.bloktema2012 bloktema 
    ON (bloktema.bloknr = blokAfgroed.bloknr) 
INNER JOIN [CTtoolsTema].dbo.Area omraade 
    ON omraade.Geom.STIntersects(bloktema.GEOM) = 1 
where omraade.Id = 296 
     AND blokAfgroed.[Year] = 2012 


SELECT 
ROUND(SUM(AGLR  * BlokInsideAreaFactor), 2) AS AGLRSum, 
ROUND(SUM(Vaarsaed * BlokInsideAreaFactor), 2) AS VaarsaedSum, 
ROUND(SUM(Vintsaed * BlokInsideAreaFactor), 2) AS VintsaedSum, 
ROUND(SUM(Oliefroe * BlokInsideAreaFactor), 2) AS OliefroeSum, 
ROUND(SUM(Baelgsaed * BlokInsideAreaFactor), 2) AS BaelgsaedSum 
FROM @TempTable 

... 이제 쿼리는 15 분이 아니라 약 11 초가 걸립니다.

다른 사람에게 도움이되기를 바랍니다.

1

왜 변수를 선언하고 필요한 데이터 집합이나 값을 변수에 넣은 다음 변수를 참조하여 모든 계산을 수행해야합니까? 그렇다면 그 가치를 한 번만 찾아야합니다.

당신이 그렇게하지 않으려면, 당신은 CTE (Common Table Expression) 테이블을 만들고, 그렇게 할 수 있습니다 reference and join 대신 where 절에 아무것도의 테이블 수 있습니다.

SQL Server를 사용하지 않는 경우 임시 테이블을 사용할 수 있습니다.