Оптимизация процедуры. Помогите! Не понимаю, чего он хочет!

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Оптимизация процедуры. Помогите! Не понимаю, чего он хочет!

Сообщение Дмитрий » 16 дек 2004, 14:42

Привет всем!
Имеем IB 6.5 на NT. Помогите оптимизнуть процедуру. Вот текст:

Код: Выделить всё

SELECT MAX( DIV_99.VIPLATA ) VIPLATA, SUM( DIV_99.DVD_SUM ) DVD_SUM
     FROM DIV_99
      INNER JOIN PAY_HISTORY ON (DIV_99.YEAR_VIP = PAY_HISTORY.YEAR_VIP) AND
                               (DIV_99.SCH_DEP = PAY_HISTORY.SCH_DEP)
     INNER JOIN COUNTERS ON (DIV_99.YEAR_VIP = COUNTERS.YEAR_VIP)
     WHERE (PAY_HISTORY.REP_RAO_NUM = :REP_RAO_NUM AND PAY_HISTORY.PAY_SUM > 0) AND
           (COUNTERS.JURIDICAL_ACC = :ACCOUNT OR COUNTERS.PHYSICAL_ACC = :ACCOUNT)
     GROUP BY DIV_99.VIPLATA
     HAVING MAX( DIV_99.VIPLATA ) IS NOT NULL
     INTO :VIPLATA, :DVD_SUM
Эта кусок процедуры вешает сервер на 100%. Причем на таблице PAY_HISTORY есть индекс по полям SCH_DEP, YEAR_VIP. Но он не используется при выполнении. Может подскажете, какой надо индекс сделать или как процедуру изменить, что бы она быстро выполнялась? Записей во всех таблицах (кроме COUNTERS - в ней 15) примерно 7 млн.[/code]

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 16 дек 2004, 15:58

Дмитрий, зачем вот такой финт нужен:
в select секции у тебя MAX( DIV_99.VIPLATA ),
а в group by ты по полю DIV_99.VIPLATA делаешь группировку и
в having MAX( DIV_99.VIPLATA ) проверяешь на NULL?
Если уж группировать по полю то зачем нужен MAX? В этом случае и
having не нужен, проверяй DIV_99.VIPLATA IS NOT NULL в where.

В COUNTERS - 15 млн или штук записей? DIV_99 и PAY_HISTORY одинаково толстые - по 7 млн?

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 16 дек 2004, 16:12

в select секции у тебя MAX( DIV_99.VIPLATA ),
- дык потому, что дальше SUM считаю
В COUNTERS - 15 млн или штук записей?
- В COUNTERS - 15 штук записей
DIV_99 и PAY_HISTORY одинаково толстые - по 7 млн?
- ага, почти одинаковые
проверяй DIV_99.VIPLATA IS NOT NULL в where
- с этим согласен, проверю, но мне кажется, что быстрее не будет
Медленно работает связка DIV_99 --> PAY_HISTORY

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 16 дек 2004, 16:29

Ты бы план привел, что-ли. У тебя, похоже, порядок джойна выбран неверный.

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 16 дек 2004, 16:34

Либо MAX, либо GROUP BY смысла не имеют. В зависимости от того, по чему делаешь SUM. HAVING можно вообще выкинуть или внести условие внутрь.
Последний раз редактировалось dimitr 16 дек 2004, 16:36, всего редактировалось 1 раз.

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 16 дек 2004, 16:35

> > в select секции у тебя MAX( DIV_99.VIPLATA ),
> дык потому, что дальше SUM считаю

И что? :shock: Значит надо над полем из группировки еще и MAX делать?

> > проверяй DIV_99.VIPLATA IS NOT NULL в where
> с этим согласен, проверю, но мне кажется, что быстрее не будет

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

В запросе попробуй зайти от "маленькой" таблички COUNTERS.

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 16 дек 2004, 16:58

Ты бы план привел, что-ли. У тебя, похоже, порядок джойна выбран неверный.
PLAN SORT (JOIN (PAY_HISTORY INDEX (PH_6,PH_4),COUNTERS INDEX (CNT_1),DIV_99 INDEX (DV99_11)))

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 16 дек 2004, 17:09

> > в select секции у тебя MAX( DIV_99.VIPLATA ),
> дык потому, что дальше SUM считаю

И что? Значит надо над полем из группировки еще и MAX делать?
Что-то из старых знаний мне подсказывает, что если есть группировка, то все поля выборки д.б. с использованием агрегатных функций. Или это еще в совсем старом SQL было?

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 16 дек 2004, 18:49

Внес все изменения, которые мне советовали. План выполнения не изменился, загрузка сервера - 100%.
Еще будут мысли?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 16 дек 2004, 20:41

как то странно это. и не понятно, что у тебя в результате получилось.

вообще запрос должен быть такой:

Код: Выделить всё

SELECT DIV_99.VIPLATA, SUM( DIV_99.DVD_SUM ) DVD_SUM
     FROM DIV_99
...
GROUP BY DIV_99.VIPLATA 
Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?

p.s.

> > в select секции у тебя MAX( DIV_99.VIPLATA ),
> дык потому, что дальше SUM считаю

group by делается так:
select полегруппировки, агрегат, [агрегат]...
group by полегруппировки

и чего ты там дальше делаешь, никого не колышет.[/quote]

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 17 дек 2004, 09:41

Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?
- пока не попробовал. Сейчас переделаю, а потом расскажу о результатах.

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 17 дек 2004, 11:54

Цитата:
Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?

- пока не попробовал. Сейчас переделаю, а потом расскажу о результатах.
Попробовал. План выполнения не изменился.
Еще есть мысли?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 17 дек 2004, 13:20

Дмитрий писал(а):
Цитата:
Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?

- пока не попробовал. Сейчас переделаю, а потом расскажу о результатах.
Попробовал. План выполнения не изменился.
Еще есть мысли?
Есть. Ты что-то не то попробовал, раз план не меняется. И оно оказалось невкусным. От перестановки мест слагаемых в INNER JOIN сумма не меняется. Управлять следованием таблиц надо так:

Скажем,

Select ...
From T1 Inner Join T2
On T1.PK=T2.FK


у оптимизатора есть выбор - пустить T1 натуралом ведущей, T2 по FK, или T2 натуралом ведущей, T1 по PK. Если он неправ, то например

Select ...
From T1 Inner Join T2
On T1.PK=T2.FK+0


лишает его этого выбора и оставляет едиственно возможный вариант - второй.

Дмитрий
Сообщения: 127
Зарегистрирован: 26 окт 2004, 11:05

Сообщение Дмитрий » 22 дек 2004, 16:24

Снова всем привет!
Никак проблема не решается.
Может кто перепишет кусочек процедуры со своей точки зрения? Просто у меня свой стиль написания SQL-запрсов, я никак не могу в корне по другому его написать. Помогите! Серевер занят на 100%!

Ответить