我有一个如下所示的查询:
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次(每列一次)。问题是,查询变得非常慢,就像这样。查询大约需要15分钟,包含大约4000行。不幸的是,我们有硬件老化,并在SQLServer 2012 Express上运行查询。
我查看了索引,似乎无法进一步优化。为什么看起来像这样的查询变得如此缓慢,最重要的是有一种方法来优化它?
更新
所涉及的表格如下:
BlokAfgroedeGrp:
Bloktema2012:
区域:
我确保索引上没有任何碎片。
答案 0 :(得分:2)
我最近在了解临时表后回到了这个问题。我已经能够优化查询:
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
...所以现在查询大约需要11秒,而不是15分钟。
希望它可以帮助别人!
答案 1 :(得分:1)
为什么不声明变量,将所需的数据集或值放入变量中,然后引用变量进行所有计算?然后你只需要找到一次该值。
如果您不想这样做,可以创建一个 CTE (Common Table Expression) 表格,这样您就可以 reference and join 改为该表格在where
子句中做任何事情。
如果您没有使用SQL Server,那么您可以查看使用临时表。