-2

我有多个查询,OUTER APPLY但所有表在连接列上都有主键(所以这里使用聚集索引)所以我不知道如何进一步优化这个查询。此外,这里不可能使用索引视图,因为它们禁止使用ORDER BYand 。TOP

所以我有

  • Fields具有Id主键和大量其他列的表。

  • WeatherHistory具有复杂主键 ( FieldIdand [Date]) 和很多列的表,

  • NdviImageHistory具有FieldId, [Date],[Base64]列(复杂主键FieldId[Date])的表[Base64]存储图像 base64,

  • NaturalColorImageHistory具有FieldId, [Date],[Base64]列(复杂主键FieldId[Date])的表[Base64]存储图像 base64,

  • NdviHistory带有FieldId, [Date],MeanNdvi列的表(复杂的主键FieldId[Date]),

  • FieldSeasonHistory具有Field, StartDate,EndDate列的表(复杂主键FieldId[Date])。

我的查询

SELECT Fields.*,
    WeatherHistory.TempSumC AS CurrentTempSumC,
    TempSumF AS CurrentTempSumF,
    PrecipitationSumMm AS CurrentPrecipitationSumMm,
    nih.[Base64] AS CurrentNdviImageBase64,
    ncih.[Base64] AS CurrentNaturalColorImageBase64,
    MeanNdvi AS CurrentMeanNdvi,
    IsOpenSeason
FROM Fields
LEFT JOIN WeatherHistory ON FieldId = Id AND [Date] = CAST(GETUTCDATE() AS DATE)
OUTER APPLY
(
    SELECT TOP 1 [Base64]
    FROM NdviImageHistory
    WHERE FieldId = Id
    ORDER BY [Date] DESC
) nih
OUTER APPLY
(
    SELECT TOP 1 [Base64]
    FROM NaturalColorImageHistory
    WHERE FieldId = Id
    ORDER BY [Date] DESC
) ncih
OUTER APPLY
(
    SELECT TOP 1 MeanNdvi
    FROM NdviHistory
    WHERE FieldId = Id
    ORDER BY [Date] DESC
) nh
OUTER APPLY
(
    SELECT TOP 1 CASE WHEN EndDate IS NULL THEN 1 ELSE 0 END AS IsOpenSeason
    FROM FieldSeasonHistory
    WHERE FieldId = Id
    ORDER BY [StartDate] DESC
) fsh
WHERE UserId = (SELECT Id FROM Users WHERE Email = @email) AND IsArchived = 0

我没有创建任何索引,因为我认为自动生成的集群索引(基于主键)应该足够了(但我可能是错的)。此查询执行大约 15 秒,但我想减少查询时间。


编辑:添加索引UserIdIsArchived表的列Fields。查询执行计划:

在此处输入图像描述


** 编辑 2:** 统计数据:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(13 row(s) affected)
Table 'FieldSeasonHistory'. Scan count 13, logical reads 26, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'NdviHistory'. Scan count 13, logical reads 26, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'NaturalColorImageHistory'. Scan count 13, logical reads 26, physical reads 0, read-ahead reads 0, lob logical reads 604, lob physical reads 0, lob read-ahead reads 0.
Table 'NdviImageHistory'. Scan count 13, logical reads 39, physical reads 0, read-ahead reads 0, lob logical reads 68, lob physical reads 0, lob read-ahead reads 0.
Table 'WeatherHistory'. Scan count 0, logical reads 39, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Users'. Scan count 0, logical reads 228, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Fields'. Scan count 1, logical reads 19, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 15 ms,  elapsed time = 16 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
4

2 回答 2

1

每个表都需要多列索引。索引应该是 where 中的列,the 中的列,order by然后是 .中的列select。例如:

  • NdviImageHistory(FieldId, [Date], [Base64])
  • NaturalColorImageHistory(FieldId, [Date], [Base64])
  • 等等。
于 2018-03-08T11:43:20.123 回答
-1

像这样更新您的查询。

SELECT Fields.*,
    WeatherHistory.TempSumC AS CurrentTempSumC,
    TempSumF AS CurrentTempSumF,
    PrecipitationSumMm AS CurrentPrecipitationSumMm,
    nih.[Base64] AS CurrentNdviImageBase64,
    ncih.[Base64] AS CurrentNaturalColorImageBase64,
    MeanNdvi AS CurrentMeanNdvi,
    IsOpenSeason
FROM Fields
LEFT JOIN WeatherHistory ON FieldId = Id AND [Date] = CAST(GETUTCDATE() AS DATE)
OUTER APPLY
(
    SELECT MAX(NdviImageHistory.ID) MAX_ID
    FROM NdviImageHistory
    WHERE FieldId = Id

) nih_ID
OUTER APPLY
(
    SELECT [Base64] FROM NdviImageHistory X WHERE X.ID = nih_ID.MAX_ID
)nih

用户更外部申请所有这些表 {nih , ncih, nh, fsh } 并尝试这个。

我只使用 1 个外部 [nih]

从 OUTER APPLY 联接中删除 TOP 1 和 Order by

于 2018-03-08T12:16:10.997 回答