Я использую Linq2Sql в качестве ORM и испытываю следующую проблему: у меня есть 2 таблицы, давайте назовем их client (id, name) и client_action (id, clientid, date). Таблица 'client' содержит клиентов, а client_action содержит журнал действий пользователя, и мне нужно только первое из них.
Был запрос linq2sql (с подкачкой и сортировкой), который привел к следующему sql:
SELECT TOP (10) /* columns here */
FROM (
SELECT /* columns here */
FROM [dbo].[client] AS [t0]
CROSS APPLY ((
SELECT NULL AS [EMPTY]
) AS [t8]
OUTER APPLY (
SELECT [t9].[source]
FROM [action] AS [t9]
INNER JOIN (
SELECT MIN([t10].[actionID]) AS [value], [t10].[ClientID]
FROM [client_action] AS [t10]
GROUP BY [t10].[clientID]
) AS [t11] ON [t9].[ID] = [t11].[value]
WHERE [t0].[ID] = [t11].[ClientID]
) AS [t12])
) AS [t17]
WHERE /* filter for fields from the client table */
ORDER BY [t17].[date_created] DESC
В этом запросе произошла логическая ошибка, и я изменил ее. Теперь сгенерированный sql выглядит так:
SELECT TOP (10) /* columns here */
FROM (
SELECT /* columns here */
FROM (
SELECT /* columns here */
FROM [dbo].[client] AS [t0]
CROSS APPLY ((
SELECT NULL AS [EMPTY]
) AS [t3]
OUTER APPLY (
SELECT [t7].[value]
FROM (
SELECT [t5].[ClientID], (
SELECT TOP (1) [t6].[ID]
FROM [client_action] AS [t6]
WHERE [t5].[clientID] = [t6].[clientID]
ORDER BY [t6].[date_created]
) AS [value]
FROM (
SELECT [t4].[clientID]
FROM [client_action] AS [t4]
GROUP BY [t4].[clientID]
) AS [t5]
) AS [t7]
WHERE [t0].[ID] = [t7].[clientID]
) AS [t8])
LEFT OUTER JOIN [client_action] AS [t9] ON [t8].[value] = [t9].[ID]
) AS [t26]
) AS [t27]
WHERE /* filter for fields from client table */
ORDER BY [t27].[date_created] DESC
И возникает проблема с производительностью. Я выполнил оба запроса с «SET STATISTICS IO ON» и получил интересные результаты:
- для первого запроса:
- клиентская таблица отфильтрована
- «10 лучших» применено
- применено «перекрестное применение» для итоговых 10 записей
- для второго запроса:
- таблица клиентов отфильтрована (найдено около 10K записей)
- применяется перекрестное применение для 10K записей
- применяется 10 лучших
Таким образом, второй запрос работает намного медленнее. Есть ли способ «подправить» запрос таким образом, чтобы после применения фильтра «перекрестное применение» применялось по возможности?
Проблема в том, что есть 2 'перекрестных применения и еще пара соединений, и все это делает его работу очень медленной. Я создал индексы, которые могли бы повысить скорость запроса, но все еще достаточно медленную, чтобы раздражать.
help help help .