Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите понять причину  [new]
koren85
Member

Откуда:
Сообщений: 5
Добрый день! Помогите новичку.
Есть некий код который до недавнего времени выполнялся очень быстро (около 3х секунд). Сейчас же он выполняется ооочень долго! Опытным путем найдено, что тормозит в следующем куске кода

SELECT DISTINCT [pprServ_PPR_SERV].[A_ID] AS [id_id],
       [pprServ_PPR_SERV].[A_ID] AS [id]
FROM   [PPR_SERV] [pprServ_PPR_SERV]
       INNER JOIN [WM_PAIDAMOUNTS] [wmPaidAmount]
            ON  [pprServ_PPR_SERV].[A_ID] = [wmPaidAmount].[A_PAYNAME]
WHERE  (
           (
               [pprServ_PPR_SERV].[A_STATUS] = 10
               OR ([pprServ_PPR_SERV].[A_STATUS] IS NULL)
           )
       )
       AND (
               wmPaidAmount.ouid IN ((
                                        SELECT [wmPaidAmounts_WM_PAIDAMOUNTS].[OUID] AS 
                                               [ouid]
                                        FROM   [WM_PAIDAMOUNTS] 
                                               [wmPaidAmounts_WM_PAIDAMOUNTS]
                                               INNER JOIN [WM_PAYMENT] 
                                                    [wmPayment_WM_PAYMENT]
                                                    ON  
                                                        [wmPaidAmounts_WM_PAIDAMOUNTS].[A_PAYMENT] = 
                                                        [wmPayment_WM_PAYMENT].[OUID]
                                                    AND (
                                                            (
                                                                (
                                                                    [wmPayment_WM_PAYMENT].[A_STATUS]
                                                                    = 10
                                                                    OR ([wmPayment_WM_PAYMENT].[A_STATUS] IS NULL)
                                                                )
                                                            )
                                                    )
                                                    
                                                    
                                               INNER JOIN [SPR_PAY_TYPE] 
                                                    [sprPayType_SPR_PAY_TYPE]
                                                    ON  [wmPayment_WM_PAYMENT].[DELIVERYWAY] = 
                                                        [sprPayType_SPR_PAY_TYPE].[A_ID]
                                               INNER JOIN [SPR_DELIVERTYPES] 
                                                    [T1459146132]
                                                    ON  [wmPayment_WM_PAYMENT].[A_DELIVERY_TYPES] = 
                                                        [T1459146132].[OUID]
                                        WHERE  ([T1459146132].[A_COD] = '4'))))


Индексы не менялись, перестройка индексов, обновление статистики ежедневно. Складывается ощущение что оптимизатор не строит нормальный план выполнения.

Выполнения запроса не дождался, но предварительный план прикреплю.

По сути у меня не осталось идей о том, что же могло так повлиять на выполнение.

Заранее выражаю благодарность всем откликнувшимся!

К сообщению приложен файл (pred.sqlplan - 42Kb) cкачать
10 июл 16, 12:09    [19391564]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
koren85
Есть некий код который до недавнего времени выполнялся очень быстро (около 3х секунд). Сейчас же он выполняется ооочень долго! Опытным путем найдено, что тормозит в следующем куске кода
Индексы не менялись, перестройка индексов, обновление статистики ежедневно. Складывается ощущение что оптимизатор не строит нормальный план выполнения.

Выполнения запроса не дождался, но предварительный план прикреплю.

По сути у меня не осталось идей о том, что же могло так повлиять на выполнение.

Размеры таблиц тоже имеют значение.

Запрос написан убого. Я б сказал точнее, но зобанят.

1. Переписать БЕЗ in. Разучите exists, что ли?
2. Уберите Join из под группировки. И здесь тоже явно нужен тупой exists.
3. Опосля этого - посмотрите есть ли нужные индексы.

ЗЫ. 3 (три) секунды - это очень долго.
10 июл 16, 12:59    [19391646]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
SELECT s.A_ID AS id
   FROM   dbo.PPR_SERV as s
   WHERE  exists (  платеж ? )
10 июл 16, 13:06    [19391657]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
koren85
Member

Откуда:
Сообщений: 5
Увы, я не разработчик. С недавнего времени приобщен к обслуживанию БД. С утверждением, что код написан криво согласен, но он не мой. Если рассматривать вопрос так, что один и тот же код на одних и тех же данных выполняется совершенно разно по времени. И планы обслуживания не менялись... Есть ли иной способ повлиять на время выполнения, кроме как переписать запрос?


P.S. то что код оптимизировать надо полностью согласен.
10 июл 16, 13:09    [19391661]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
Попрыгать с бубном можно.
Но переписать на порядок эффективнее.

ЗЫ. Мне лень, но сщас или завтра подтянуться молодые - перепишут.
10 июл 16, 13:17    [19391675]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
Вот эквивалент твоего уродца. Без ненужного join и группировки.

SELECT s.A_ID AS id_id, s.A_ID AS id
  FROM PPR_SERV as s
  WHERE ( s.A_STATUS = 10 OR s.A_STATUS IS NULL )
        AND exists( SELECT *
                      FROM WM_PAIDAMOUNTS as pa
                           INNER JOIN WM_PAYMENT as pm ON pa.A_PAYMENT = pm.OUID 
                           INNER JOIN SPR_PAY_TYPE as spt ON pm.DELIVERYWAY = spt.A_ID
                           INNER JOIN SPR_DELIVERTYPES as sd ON pm.A_DELIVERY_TYPES = sd.OUID
                      WHERE  pa.A_PAYNAME = s.A_ID and sd.A_COD = '4' and ( pm.A_STATUS = 10 OR pm.A_STATUS IS NULL )
                  )
10 июл 16, 13:43    [19391712]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
koren85
Member

Откуда:
Сообщений: 5
Спасибо за помощь, завтра скажу разработчикам чтобы переделали скрипт. Я попробовал его выполнить переписав через EXISTS, он отработал менее секунды!

Но вопрос все же остался, из-за чего он перестал выполняться.... Остается только гадать.
10 июл 16, 14:33    [19391802]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
koren85
Спасибо за помощь, завтра скажу разработчикам чтобы переделали скрипт. Я попробовал его выполнить переписав через EXISTS, он отработал менее секунды!

Но вопрос все же остался, из-за чего он перестал выполняться.... Остается только гадать.


Чего гадать то?

Когда говно-разработчики пишут запрос - им "лишь бы тока работал".
Ну он и работает... на небольших объемах данных.
Но время исполнения "сферического запроса в вакууме" зависит от объема данных N (N = число строк) в таблицах.
Для хорошего запроса, время исполнения зависит от количества данных "ваще никак", т.е. ~log(N).
Но "умельцы" способны написать и ~N^2 или ~N^3, а особо одаренные ~N!.
Такие чудесные запросы очень быстро становятся "внезапно тормозными".

ЗЫ. План запроса смотрят только от безысходности.
10 июл 16, 16:13    [19391975]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
AlanDenton
Member [скрыт]

Откуда:
Сообщений: 1004
Попробуйте такой вариант:

SELECT s.A_ID AS [id_id], s.A_ID AS [id]
FROM dbo.PPR_SERV s
WHERE (
            s.A_STATUS = 10
        OR
            s.A_STATUS IS NULL
    )
    AND EXISTS(
            SELECT *
            FROM dbo.WM_PAIDAMOUNTS a
            JOIN dbo.WM_PAYMENT p ON a.A_PAYMENT = p.OUID
            JOIN dbo.SPR_DELIVERTYPES d ON p.A_DELIVERY_TYPES = d.OUID
            WHERE d.A_COD = '4'
                AND s.A_ID = a.A_PAYNAME
                AND (
                            p.A_STATUS = 10
                        OR
                            p.A_STATUS IS NULL
                    )
        )
11 июл 16, 10:11    [19393528]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
AlanDenton
Попробуйте такой вариант:

SELECT s.A_ID AS [id_id], s.A_ID AS [id]
FROM dbo.PPR_SERV s
WHERE (
            s.A_STATUS = 10
        OR
            s.A_STATUS IS NULL
    )
    AND EXISTS(
            SELECT *
            FROM dbo.WM_PAIDAMOUNTS a
            JOIN dbo.WM_PAYMENT p ON a.A_PAYMENT = p.OUID
            JOIN dbo.SPR_DELIVERTYPES d ON p.A_DELIVERY_TYPES = d.OUID
            WHERE d.A_COD = '4'
                AND s.A_ID = a.A_PAYNAME
                AND (
                            p.A_STATUS = 10
                        OR
                            p.A_STATUS IS NULL
                    )
        )


А чо не выкинул весь exists?
11 июл 16, 11:13    [19393839]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
AlanDenton
Member [скрыт]

Откуда:
Сообщений: 1004
aleks2
А чо не выкинул весь exists?

Можно что-то по конструктивнее услышать?
11 июл 16, 11:26    [19393945]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
koren85
Member

Откуда:
Сообщений: 5
Разработчики дали ответ, что данный код формируется приложением автоматически. Трогать приложение они не могут. Значит остается только средствами обслуживания как-то влиять на выполнение этого запроса. Куда копать?
11 июл 16, 11:42    [19394092]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
AlanDenton
Member [скрыт]

Откуда:
Сообщений: 1004
aleks2, извиняюсь. Не увидел, что такой же вариант запроса предложили.
11 июл 16, 11:55    [19394186]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
aleks2
Guest
AlanDenton
Не увидел, что такой же вариант запроса предложили.

Не такой же, а гораздо правильнее.

koren85
Разработчики дали ответ, что данный код формируется приложением автоматически. Трогать приложение они не могут. Значит остается только средствами обслуживания как-то влиять на выполнение этого запроса. Куда копать?


Вглубь.

ЗЫ. Скушно это.
11 июл 16, 12:17    [19394343]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
Denis Reznik
Member

Откуда: Киев
Сообщений: 156
koren85
Разработчики дали ответ, что данный код формируется приложением автоматически. Трогать приложение они не могут. Значит остается только средствами обслуживания как-то влиять на выполнение этого запроса. Куда копать?


да ленятся они :) это ж надо переписать код, и сразу подумать что он сгенерирует и проверить что сгенерировал.
11 июл 16, 13:13    [19394699]     Ответить | Цитировать Сообщить модератору
 Re: Помогите понять причину  [new]
invm
Member

Откуда: Москва
Сообщений: 9723
koren85
Разработчики дали ответ, что данный код формируется приложением автоматически. Трогать приложение они не могут.
Сделайте их ЗП пропорциональной производительности запросов - сразу все смогут.
koren85
Куда копать?
В качестве костыля попробуйте создать индекс: WM_PAYMENT (A_STATUS) include (OUID, DELIVERYWAY, A_DELIVERY_TYPES)
11 июл 16, 13:33    [19394852]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить