Справка по оптимизации представления SQL Server (повторные подзапросы, случай, когда и так далее ...) - PullRequest
2 голосов
/ 25 января 2011

Мне нужна помощь в оптимизации представления MSSQL, которое, честно говоря, слишком сложное для моих знаний.

Представление работает хорошо, но я хотел бы переписать его, используя меньше подзапросов или лучшую структуручтобы упростить его и использовать меньше ресурсов сервера.

Основная проблема - это СЛУЧАЙ, КОГДА с тем же подзапросом повторяется 4 раза ... Я пытался понять, могу ли я поместить его в переменную и использовать дляСЛУЧАЙ вместо того, чтобы повторять запрос каждый раз, но мне кажется, что это невозможно ...

Вот запрос

SELECT     dbo.MACCHINE.id_macchina, [...] dbo.VIEW_CANTIERI.indirizzo,

(SELECT     TOP (1) data_fine
FROM          dbo.MANUTENZIONI
WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC)
AS ultima_manutenzione, 

DATEDIFF(day,
    (SELECT     TOP (1) data_fine
    FROM          dbo.MANUTENZIONI AS MANUTENZIONI_1
    WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
    ORDER BY data_fine DESC), GETDATE())
AS data_diff, 

(CASE WHEN 
    stato = 0 
    THEN 'GREY' 
WHEN stato = 2 
    THEN 'BLACK' 
WHEN stato = 1 
    THEN
        (CASE WHEN 
            DATEDIFF(day,
            (SELECT     TOP (1) data_fine
            FROM          dbo.MANUTENZIONI AS MANUTENZIONI_1
            WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
            ORDER BY data_fine DESC), GETDATE()) >= 90 
        THEN 'RED'

        WHEN 
            DATEDIFF(day,
            (SELECT     TOP (1) data_fine
            FROM          dbo.MANUTENZIONI AS MANUTENZIONI_1
            WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
            ORDER BY data_fine DESC), GETDATE()) >= 80 
        THEN 'ORANGE' 

        WHEN
            DATEDIFF(day,
            (SELECT     TOP (1) data_fine
            FROM          dbo.MANUTENZIONI AS MANUTENZIONI_1
            WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
            ORDER BY data_fine DESC), GETDATE()) >= 60 
        THEN 'YELLOW'

        WHEN
            (SELECT     TOP (1) data_fine
            FROM          dbo.MANUTENZIONI AS MANUTENZIONI_1
            WHERE      (id_macchina = dbo.MACCHINE.id_macchina)
            ORDER BY data_fine DESC) IS NULL
        THEN 'RED' ELSE 'GREEN' 

        END) 

END) 
AS colore FROM         dbo.MACCHINE INNER JOIN
                  dbo.MACCHINE_MODELLI ON dbo.MACCHINE.id_modello = dbo.MACCHINE_MODELLI.id_modello INNER JOIN
                  dbo.MACCHINE_TIPOLOGIE ON dbo.MACCHINE_MODELLI.id_tipologia = dbo.MACCHINE_TIPOLOGIE.id_tipologia INNER JOIN
                  dbo.VIEW_CANTIERI ON dbo.MACCHINE.id_cantiere = dbo.VIEW_CANTIERI.id_cantiere INNER JOIN
                  dbo.MACCHINE_PRODUTTORI ON dbo.MACCHINE_MODELLI.id_produttore = dbo.MACCHINE_PRODUTTORI.id_produttore INNER JOIN
                  dbo.CLIENTI ON dbo.VIEW_CANTIERI.id_cliente = dbo.CLIENTI.id_cliente WHERE     (dbo.MACCHINE._del = 'N')

Любое предложение действительно приветствуется, если вам нужна дополнительная информация од.б. постараюсь это предоставить ...

Ответы [ 2 ]

2 голосов
/ 25 января 2011

Извините, если вы уже сделали это, но я бы предложил использовать SHOWPLAN (ctrl + L) или инструменты повышения производительности, если они у вас есть. Убедитесь, что именно эти операторы CASE вызывают проблему - узким местом может быть, например, одно из объединений, отсутствующий индекс или устаревшая статистика, способствующая плохому плану выполнения.

Если представление читается гораздо чаще, чем записывается, или для него не нужно иметь точно обновленные данные (т. Е. Вы можете кэшировать результаты каждый день и читать представление из обновления вчерашней ночи), рассмотрите возможность использования индексированного представления. Это кэширует представление, как если бы оно было таблицей, поэтому операции (включая и CASE, и JOIN) не выполняются каждый раз, когда вы читаете из таблицы (наличие индекса также ускоряет использование). В качестве альтернативы, если только последние данные изменились, вы можете попробовать разбить индексированное представление по дате.

2 голосов
/ 25 января 2011

Я заметил, что вы используете TOP (1), так что это должно быть 2005 или выше.Вы можете сохранить результат датировки в подзапросе OUTER APPLY, чтобы он оценивался только один раз.

SELECT
    M.id_macchina,
    [...],
    V.indirizzo,
    MA.data_fine AS ultima_manutenzione, 
    MA.data_diff, 
    CASE
    WHEN stato = 0 THEN 'GREY' 
    WHEN stato = 2 THEN 'BLACK' 
    WHEN stato = 1 THEN
        CASE
        WHEN MA.data_diff >= 90   THEN 'RED'
        WHEN MA.data_diff >= 80   THEN 'ORANGE' 
        WHEN MA.data_diff >= 60   THEN 'YELLOW'
        WHEN MA.data_fine IS NULL THEN 'RED'
        ELSE 'GREEN' 
        END
    END AS colore
FROM dbo.MACCHINE M
INNER JOIN dbo.MACCHINE_MODELLI I ON M.id_modello = I.id_modello
INNER JOIN dbo.MACCHINE_TIPOLOGIE T ON I.id_tipologia = T.id_tipologia
INNER JOIN dbo.VIEW_CANTIERI V ON M.id_cantiere = V.id_cantiere
INNER JOIN dbo.MACCHINE_PRODUTTORI P ON I.id_produttore = P.id_produttore
INNER JOIN dbo.CLIENTI C ON V.id_cliente = C.id_cliente
OUTER APPLY (SELECT TOP (1)
                MA.data_fine,
                DATEDIFF(day, MA.data_fine, GETDATE()) AS data_diff
            FROM    dbo.MANUTENZIONI AS MA
            WHERE   MA.id_macchina = M.id_macchina
            ORDER BY MA.data_fine DESC) MA
WHERE M._del = 'N'
...