次のようなクエリがあります。
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 回 (列ごとに 1 回) 計算されるのではなく、行ごとに 1 回だけ計算されるため、この方法でクエリを最適化することを最初に考えました。問題は、このように実行すると、クエリが非常に遅くなるということです。約 4000 行を含むクエリには約 15 分かかります。残念ながら、ハードウェアが古くなっているため、SQLServer 2012 Express でクエリを実行しています。
私はインデックスを見てきましたが、そのようにさらに最適化することはできません。このように見えるクエリが非常に遅くなるのはなぜですか? 最も重要なのは、それを最適化する方法があることです。
アップデート:
関連するテーブルは次のようになります。
ブロックアフグローブグループ:
- 列: Id (主キー、ID)、BlokNr、年、AGLR、Vaarsaed、Vintsaed...など。
- インデックス: Id でクラスター化され、BlokNr + 年でクラスター化されていない一意のインデックス
ブロックテマ2012:
- 列: Id (主キー、ID)、BlokNr、Geom (ジオメトリ) + その他 (重要ではない)
- インデックス: Id でクラスター化、Geom で空間、非固有 - Id + BlokNr で非クラスター化、非固有 - BlokNr のみで非クラスター化。
領域:
- 列: Id (主キー、ID)、Geom (ジオメトリ) + その他 (重要ではない)
- インデックス: Id でクラスター化、Geom で空間
インデックスに断片化がないことを確認しました。