Производительность выполнения вложенных запросов Sql

Ниже приведен мой вложенный SQL-запрос:

SELECT M.UserID, SUM(M.Browser)
FROM
(
    SELECT UserID, X.Browser
    FROM
    (
        SELECT UserName, PCMLogEventID, MAX(Browser) AS Browser
        FROM [PCMDBSERVER].[MISTestPCM_Raw].[dbo].[PCM_Log_FilterSwitchData] 
        WHERE [DateTime] BETWEEN '6/12/2013 12:00:00 AM' AND '6/12/2013 11:59:59 PM'
        GROUP BY UserName, PCMLogEventID
    ) X
    INNER JOIN ( 
        SELECT * 
        FROM PCM_Stat_UserRepository 
        WHERE MachineID='All' 
    ) Y
    ON X.UserName = Y.UserName
) M
GROUP BY M.UserID

Время выполнения внутреннего запроса с предложением select (Select UserID, X.Browser) занимает всего 1 секунду, возвращая всего 197 строк. Однако, когда я выполняю весь вложенный запрос, для возврата результата требуется почти 6 минут. Может ли кто-нибудь помочь мне понять, почему это занимает так много времени?

РЕДАКТИРОВАТЬ: на самом деле необходим PCMLogEventID. Потому что данные в PCM_Log_FilterSwitchData примерно такие: UserName | PCMLogEventID | Браузер абв | 111 | 0,9 абс | 111 | 1.2 азбука | 222 | 1.2 азбука | 222 | 3.5 . . Таким образом, я сначала беру MAX, группируя UserName и PCMLogEventID, а затем его СУММУ.


person Lucifer    schedule 13.06.2013    source источник
comment
[PCM_Log_FilterSwitchData] это вид? А почему ты GROUP BY PCMLogEventID?   -  person Devart    schedule 13.06.2013
comment
В случае внутренних запросов для каждой строки, возвращаемой внешним запросом, выполняется внутренний запрос. Следовательно, даже если ваш внутренний запрос выполняется всего за несколько секунд, внешний запрос может возвращать много строк, что приводит к многократному выполнению внутреннего запроса.   -  person Darshan Mehta    schedule 13.06.2013
comment
@ Даршан Мехта, я с тобой не согласен - все зависит от Execution Plan.   -  person Devart    schedule 13.06.2013
comment
Обработка подзапросов объясняется здесь. /B28359_01/server.111/b28286/queries008.htm   -  person Darshan Mehta    schedule 13.06.2013
comment
Это [PCMDBSERVER].[MISTestPCM_Raw].[dbo].[PCM_Log_FilterSwitchData] на другом сервере? И можете ли вы подтвердить тег SQL Sever, который кто-то добавил?   -  person Mark Schultheiss    schedule 13.06.2013
comment
Полностью согласен с @Mark Schultheiss.   -  person Devart    schedule 13.06.2013
comment
@MarkSchultheiss, PCM_Log_FilterSwitchData находится на другом сервере, для которого я создал связанный сервер.   -  person Lucifer    schedule 13.06.2013
comment
Причина, по которой я спрашиваю, заключается в том, что иногда запрос удаленного сервера выполняет полное сканирование таблицы, и это будет обрабатывать этот подзапрос несколько раз из-за его конструкции - поэтому временная таблица с результатами может повысить производительность для этих 197 строк - не делайте этого один раз много раз. Я рекомендую вам взглянуть на фактический план выполнения в SSMS.   -  person Mark Schultheiss    schedule 13.06.2013


Ответы (2)


Это то, что сработало для меня. Я изменил порядок: сначала MAX, затем SUM, а затем JOIN.

    Select Y.UserID, P.Browser
    FROM
    (
        SELECT DISTINCT X.UserName, SUM(X.Browser) as Browser
        FROM
        (
            SELECT UserName, PCMLogEventID, MAX(Browser) AS Browser
            FROM [PCMDBSERVER].[MISTestPCM_Raw].[dbo].[PCM_Log_FilterSwitchData] 
            WHERE [DateTime] BETWEEN '6/12/2013 12:00:00 AM' AND '6/12/2013 11:59:59 PM'
            GROUP BY UserName, PCMLogEventID
        ) X
        GROUP BY X.UserName
        ) P
        INNER JOIN
        ( SELECT * FROM PCM_Stat_UserRepository WHERE MachineID='All' ) Y
    ON P.UserName = Y.UserName
person Lucifer    schedule 13.06.2013

Возможно, это будет полезно для вас -

SELECT M.UserID, Browser = SUM(X.Browser)
FROM
(
    SELECT 
          UserName
        , Browser = MAX(Browser) 
    FROM [PCMDBSERVER].[MISTestPCM_Raw].[dbo].[PCM_Log_FilterSwitchData] 
    WHERE [DateTime] BETWEEN '20130613 12:00:00' AND '20130613 23:59:59'
    GROUP BY UserName
) X
JOIN (
    SELECT 
          UserName
        , UserID 
    FROM dbo.PCM_Stat_UserRepository 
    WHERE MachineID = 'All' 
) M ON X.UserName = Y.UserName
GROUP BY M.UserID
person Devart    schedule 13.06.2013
comment
Это в основном то, о чем я тоже думал. Другой возможностью было бы поместить дополнительный выбор для результата [PCM_Log_FilterSwitchData] во временную таблицу и просто соединить его со вторым, возможно, отказавшись от внешнего выбора. - person Mark Schultheiss; 13.06.2013
comment
Кажется, это работает @Devart, но не могли бы вы помочь мне объяснить, как простая замена Inner Join на Join сделала волшебство? - person Lucifer; 13.06.2013
comment
Но ты пропустил PCMLogEventID, @Devart! - person Lucifer; 13.06.2013
comment
Основная магия - запрос без группировки по PCMLogEventID столбцу. INNER JOIN и JOIN равны. - person Devart; 13.06.2013