Как оптимизировать запрос - PullRequest
1 голос
/ 13 июня 2011

Я использую 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 .

...