Страница 1 из 1
Оптимизация процедуры. Помогите! Не понимаю, чего он хочет!
Добавлено: 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]
Добавлено: 16 дек 2004, 15:58
sag
Дмитрий, зачем вот такой финт нужен:
в 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 млн?
Добавлено: 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
Добавлено: 16 дек 2004, 16:29
dimitr
Ты бы план привел, что-ли. У тебя, похоже, порядок джойна выбран неверный.
Добавлено: 16 дек 2004, 16:34
dimitr
Либо MAX, либо GROUP BY смысла не имеют. В зависимости от того, по чему делаешь SUM. HAVING можно вообще выкинуть или внести условие внутрь.
Добавлено: 16 дек 2004, 16:35
sag
> > в select секции у тебя MAX( DIV_99.VIPLATA ),
> дык потому, что дальше SUM считаю
И что?

Значит надо над полем из группировки еще и MAX делать?
> > проверяй DIV_99.VIPLATA IS NOT NULL в where
> с этим согласен, проверю, но мне кажется, что быстрее не будет
Это все мои придирки, запрос прикольно выглядит. Исправления на скорость катосрофически, может быть, и не скажутся.
В запросе попробуй зайти от "маленькой" таблички COUNTERS.
Добавлено: 16 дек 2004, 16:58
Дмитрий
Ты бы план привел, что-ли. У тебя, похоже, порядок джойна выбран неверный.
PLAN SORT (JOIN (PAY_HISTORY INDEX (PH_6,PH_4),COUNTERS INDEX (CNT_1),DIV_99 INDEX (DV99_11)))
Добавлено: 16 дек 2004, 17:09
Дмитрий
> > в select секции у тебя MAX( DIV_99.VIPLATA ),
> дык потому, что дальше SUM считаю
И что? Значит надо над полем из группировки еще и MAX делать?
Что-то из старых знаний мне подсказывает, что если есть группировка, то все поля выборки д.б. с использованием агрегатных функций. Или это еще в совсем старом SQL было?
Добавлено: 16 дек 2004, 18:49
Дмитрий
Внес все изменения, которые мне советовали. План выполнения не изменился, загрузка сервера - 100%.
Еще будут мысли?
Добавлено: 16 дек 2004, 20:41
kdv
как то странно это. и не понятно, что у тебя в результате получилось.
вообще запрос должен быть такой:
Код: Выделить всё
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]
Добавлено: 17 дек 2004, 09:41
Дмитрий
Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?
- пока не попробовал. Сейчас переделаю, а потом расскажу о результатах.
Добавлено: 17 дек 2004, 11:54
Дмитрий
Цитата:
Дальше, тебе посоветовали join начать с маленькой таблицы. Результаты?
- пока не попробовал. Сейчас переделаю, а потом расскажу о результатах.
Попробовал. План выполнения не изменился.
Еще есть мысли?
Добавлено: 17 дек 2004, 13:20
Merlin
Дмитрий писал(а):Цитата:
Дальше, тебе посоветовали 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
лишает его этого выбора и оставляет едиственно возможный вариант - второй.
Добавлено: 22 дек 2004, 16:24
Дмитрий
Снова всем привет!
Никак проблема не решается.
Может кто перепишет кусочек процедуры со своей точки зрения? Просто у меня свой стиль написания SQL-запрсов, я никак не могу в корне по другому его написать. Помогите! Серевер занят на 100%!