Код разработки - Понимание того, что я вижу - PullRequest
1 голос
/ 25 июля 2011

Я начинаю с того, что говорю, что я не разработчик, и это не мой код.Как администратор базы данных, хотя он показал на табличке с точки зрения производительности.План выполнения показывает, что есть сканирование CI для таблицы 2 с псевдонимом D и таблицы 2 с псевдонимом E. Сосредоточение на таблице 2 с псевдонимом E. Сканирование исходит из подзапроса в предложении where для E.SEQ_NBR = Я также вижу далекобольше казней, чем нужно.Я знаю, что это зависит от точной структуры индекса в таблице, но на высоком уровне вполне вероятно, что я вижу сканирование CI, полученное из совокупности (мин) для каждого совпадения, которое он находит.По сути, это обход таблицы минимального SEQ_NBR для каждого совпадения по EMPLID и другим полям?

Если вероятно, это скорее результат того, как это написано (я думаю, включение CTE с некоторымиЛогика ROW_NUMBER поможет) или отсутствие индексации?Я пытаюсь избежать броска индекса в это "только потому что".Я зацикливаюсь на этом подзапросе в предложении where.

SELECT
    D.EMPLID
   ,D.JOBCODE
   ,D.DEPTID
   ,E.DUR
   ,SUM(D.TL_QUANTITY) 'YTD_TL_QUANTITY'
FROM
    Table1 B
   ,Table2 D
   ,Table2 E
WHERE
    D.TRC = B.TRC
    AND B.TL_ERNCD IN ( @0, @1, @2, @3, @4, @5, @6 )
    AND D.EMPLID = E.EMPLID
    AND D.EMPL_RCD = E.EMPL_RCD
    AND D.DUR < = E.DUR
    AND D.DUR > = '1/1/' + CAST(DATEPART(YEAR, E.DUR) AS CHAR)
    AND E.SEQ_NBR = 
                ( SELECT
                    MIN(EX.SEQ_NBR)
                  FROM
                    Table2 EX
                  WHERE
                    E.EMPLID = EX.EMPLID
                    AND E.EMPL_RCD = EX.EMPL_RCD
                    AND E.DUR = EX.DUR
                )
    AND B.EFFDT = ( SELECT
                        MAX(B_ED.EFFDT)
                    FROM
                        Table1 B_ED
                    WHERE
                        B.TRC = B_ED.TRC
                        AND B_ED.EFFDT < = GETDATE()
                  )
GROUP BY
    D.EMPLID
   ,D.JOBCODE
   ,D.DEPTID
   ,E.DUR

Ответы [ 3 ]

1 голос
/ 25 июля 2011

Коррелированные подзапросы убивают производительность.Удалите их и замените их CTE и JOIN или производными таблицами.

Попробуйте что-то вроде этого (не проверено)

SELECT
     D.EMPLID
     ,D.JOBCODE    
     ,D.DEPTID    
     ,E.DUR    
     ,SUM(D.TL_QUANTITY) 'YTD_TL_QUANTITY' 
FROM Table1 B    
JOIN Table2 D 
    ON D.TRC = B.TRC  AND D.EMPLID = E.EMPLID
JOIN Table2 E 
    ON D.EMPL_RCD = E.EMPL_RCD AND D.DUR < = E.DUR 
JOIN (SELECT MIN(EX.SEQ_NBR)FROM  Table2) EX 
    ON E.EMPLID = EX.EMPLID  
    AND E.EMPL_RCD = EX.EMPL_RCD                     
    AND E.DUR = EX.DUR  
JOIN (SELECT  MAX(B_ED.EFFDT)  
        FROM  Table1
        WHERE B_ED.EFFDT < = GETDATE()) B_ED 
    ON B.TRC = B_ED.TRC         
WHERE     B.TL_ERNCD IN ( @0, @1, @2, @3, @4, @5, @6 )           
AND D.DUR > = '1/1/' + CAST(DATEPART(YEAR, E.DUR) AS CHAR)  

Что касается неявного синтаксиса соединения, не позволяйте никому делать это снова.Это плохая методика программирования.Как администратор базы данных, вы можете сказать, что вы будете и не будете разрешать в базе данных.Просмотрите код, что входит, и не передавайте его, пока не удалите неявный синтаксис.

Почему это плохо?Во-первых, вы получаете случайные перекрестные соединения.Кроме того, с точки зрения обслуживания, вы не можете сказать, было ли перекрестное соединение случайным (и, следовательно, запрос неправильным) или намеренно.Это означает, что запрос с перекрестным соединением в нем не поддерживается.

Далее, если вам придется изменить некоторые из последующих объединений на внешние объединения и не исправить все неявные одновременно, вы можете получить неверные результаты (что может быть не замечено неопытным разработчиком.В SQL Server 2008 вы не можете использовать неявный синтаксис для внешнего объединения, но его не следовало использовать даже еще в SQl Server 2000, потому что Books Online (для SQL Server 2000) заявляет, что в некоторых случаях это неверно интерпретируется.Другими словами, синтаксис ненадежен для внешних объединений. Никогда нет оправдания использованию неявного объединения, вы ничего не получаете от них за счет использования явного объединения, и они могут создать больше проблем.

Вам необходимо обучитьваши разработчики и скажите им, что этот код (который устарел с 1992 года!) более недопустим.

1 голос
/ 25 июля 2011

Операция MIN не имеет никакого отношения к сканированию CL. MIN или Max рассчитывается с использованием сортировки. Проблема, скорее всего, заключается в том, сколько раз выполнялся подзапрос. Он должен перебирать подзапрос для каждой записи, возвращаемой в родительском запросе. CTE может быть здесь полезен в зависимости от размера таблицы 2, но я не думаю, что вам нужно беспокоиться о поиске замены для MIN () ... по крайней мере, пока.

0 голосов
/ 25 июля 2011

Это быстрый, но этот, CAST ('1/1 /' + CAST (DATEPART (YEAR, E.DUR) AS CHAR) AS DATETIME), он, вероятно, вызывает сканирование таблицы в Table2 E, поскольку должен оцениваться по каждой строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...