У меня есть таблица с 4 000 000 записей, которая растет с каждым днем.
Prices(Contract INT, Period DATE, Date DATE, PriceValue FLOAT)
Мне нужно отфильтровать цены по Дата (@dateFrom / @dateTo - это ввод пользователя) и найтиmax Дата цена за каждый уникальный Контракт / Период
Во-первых, я начал с:
SELECT p.*
FROM
(
SELECT [ContractId], [Period], MAX(p.Date) AS MaxDate FROM Prices p WITH (NOLOCK)
WHERE (@dateFrom IS NULL OR p.[Date] >= @dateFrom) AND p.[Date] <= @dateTo)
GROUP BY [ContractId], [Period]
) md
INNER JOIN Prices p WITH (NOLOCK) ON md.ContractId = p.ContractId AND md.PERIOD = p.PERIOD AND md.MaxDate = p.Date
WHERE (@dateFrom IS NULL OR p.[Date] >= @dateFrom) AND p.[Date] <= @dateTo)
Это работало нормально в течение 2-Диапазон дат 3 недели, но часто, когда запрашиваются данные за 1 год.Это занимает до 30-60 секунд ...
Затем я попробовал подход ROW_NUMBER (), но это было очень медленно ...
И, наконец, я переключаюсь на EF lamba, которая генерируетследующий запрос (немного очищен)
SELECT
[Limit1]......
FROM (SELECT
@toDate AS [p__linq__0],
@fromDate AS [p__linq__1],
[Distinct1].....
FROM ( SELECT DISTINCT
[Extent1].[ContractId] AS [ContractId],
[Extent1].[Period] AS [Period],
FROM [dbo].[Prices] AS [Extent1]
WHERE ([Extent1].[ContractId] IN ... AND ([Extent1].[Date] <= @toDate))
) AS [Distinct1] ) AS [Project2]
OUTER APPLY (SELECT TOP (1) [Project3].[Id] AS [Id], [Project3].[ContractId] AS [ContractId], [Project3].[Period] AS [Period], [Project3].[Date] AS [Date], [Project3].[PriceValue] AS [PriceValue])
FROM ( SELECT
[Extent2].....
FROM [dbo].[Prices] AS [Extent2]
WHERE ([Extent2].[ContractId] IN ... AND ([Project2].[Period] = ...)
) AS [Project3]
ORDER BY [Project3].[Date] DESC ) AS [Limit1]
Внешнее применение работало немного быстрее, но все еще 20-30 секунд.
Индексы в таблице
CREATE INDEX FilteredPricesOnlyLast
ON TradeBlotterDevPoc.dbo.Prices (ContractId, PERIOD, Date)
GO
CREATE INDEX IDX_Latest
ON TradeBlotterDevPoc.dbo.Prices (ContractId, PERIOD)
INCLUDE (Date)
GO
MSSQLStudio и Azure не дают никаких рекомендаций по индексам.
Итак, вопрос Есть ли способ выполнить эту задачу в 5 раз или быстрее, чем базовое применение GROUP BY или OUTER APPLY?Возможно, с любым другим хитрым SQL-запросом?Или есть какие-либо известные методы предварительной обработки данных?