Sql 使用多个外部应用优化查询

Sql 使用多个外部应用优化查询,sql,sql-server,query-optimization,cross-apply,outer-apply,Sql,Sql Server,Query Optimization,Cross Apply,Outer Apply,我正在使用多个外部应用的查询,但是所有表在连接列上都有主键,所以这里使用聚集索引,所以我不知道如何进一步优化此查询。此外,这里不可能使用索引视图,因为禁止使用ORDERBY和TOP 所以我有 具有Id主键和大量其他列的表字段 WeatherHistory表,包含复杂的主键字段ID和[Date]以及许多列 NdviImageHistory表,其中FieldId、[Date]、[Base64]列包含复杂主键FieldId和[Date],其中[Base64]存储图像Base64 具有FieldId、[

我正在使用多个外部应用的查询,但是所有表在连接列上都有主键,所以这里使用聚集索引,所以我不知道如何进一步优化此查询。此外,这里不可能使用索引视图,因为禁止使用ORDERBY和TOP

所以我有

具有Id主键和大量其他列的表字段

WeatherHistory表,包含复杂的主键字段ID和[Date]以及许多列

NdviImageHistory表,其中FieldId、[Date]、[Base64]列包含复杂主键FieldId和[Date],其中[Base64]存储图像Base64

具有FieldId、[Date]、[Base64]列的NaturalColorImageHistory表复杂主键FieldId和[Date],其中[Base64]存储图像Base64

字段ID为[Date],MeanNdvi列为复合主键字段ID和[Date]的NdviHistory表

FieldSeasonHistory表,包含字段、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秒,但我想减少查询时间

编辑:向字段表的UserId和IsArchived列添加索引。查询执行计划:

**编辑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.

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

NdviImageHistoryFieldId,[Date],[Base64] NaturalColorImageHistoryFieldId,[Date],[Base64] 等等
像这样更新您的查询

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个外层


从外部应用联接中删除TOP 1和Order by

我需要为每列创建单独的索引,或为多列创建单个索引?我是说每个表一个索引或每列一个索引?我也不能索引[Base64],因为它是VARCHARMAX列。@VadimOvchinnikov。然后使用前两列创建索引。这些是复合索引-包含多列的索引。好的,我明白了。对于表NdviImageHistory和NaturalColorImageHistory,已经存在聚集索引,因为前两列是复合主键。另外,我假设问题与此表有关,因为如果我从查询中删除它们,查询将在一秒钟内执行。您确定这将编译吗?是的,如果您可以为我在解决方案中提到的每个表添加更多的外部数据,它将正常工作。好的,为什么您认为这将比原始查询执行得更快?