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

Откуда:
Сообщений: 278
Доброго времени суток всем!

Подскажите, пожалуйста, можно-ли как-то оптимизировать ниже описанный код, чтобы выборка из базы происходила быстрее? На данный момент этот блок выполняется за 9 минут. Обрабатывается около 2 миллионов записей. База на Oracle 10g.

declare
       DateFrom   Date;
       DateTo     Date;
begin
    DateFrom:='01.01.07';
    DateTo:='31.12.07';
    
    For TransfersVolume in (
                              Select Bank, count(*) Kol from
                                    (Select
                                    GetSmt(DT.NumberID) Bank
                                    From
                                        Transfer DT
                                    Where
                                        DT.Test<>0
                                        DT.Paydate >= DateFrom and
                                        DT.Paydate <= DateTo and
                                        DT.State in (1212, 6565, 2233)
                                    Order by Bank)
                              Group by Bank
                              Order by Kol desc) LOOP
                              
        dbms_output.put_line(TransfersVolume.Bank)||' '||TransfersVolume.Kol); 

    End loop;
end;
18 апр 08, 19:46    [5568675]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116228
Много еще вопросов. Функция GetSmt - черный ящик...
Пока такой вопрос. А зачем Вам внутренняя сортировка order by bank ?
По моему она не очень нужна ...
18 апр 08, 19:51    [5568681]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Landgraf
Member

Откуда:
Сообщений: 278
dmidek
Много еще вопросов. Функция GetSmt - черный ящик...
Пока такой вопрос. А зачем Вам внутренняя сортировка order by bank ?
По моему она не очень нужна ...



GetSmt - это функция возвращающая идентификатор банка. Сдесь считается сколько операций совершил банк за определенный период. Потом все это дело сортируется по убыванию.
Внутренняя сортировка - пардон, это я ошибся!
18 апр 08, 20:02    [5568700]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
opt10g
Guest
Что происходит в функции GetSmt ?
нельзя ли ее алгоритм засунуть в select, чтобы не было переключений контекста?
Если нелья и DT.NumberID могут повторяться, то попробуйте функцию объявить детерминированной - если она таковой является конечно

И покажите в конце концов план запроса !
:-)
18 апр 08, 20:03    [5568704]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 63986
Блог
Landgraf

Сколько будет считаться тот же блок, если вместо GetSmt поставить простое выражение, скажем, mod(dt.numberid, 100)?
18 апр 08, 20:06    [5568709]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Landgraf
Member

Откуда:
Сообщений: 278
opt10g


И покажите в конце концов план запроса !
:-)


SELECT STATEMENT, GOAL = CHOOSE Cost=293 Cardinality=68728 Bytes=1443288
FILTER TABLE ACCESS BY INDEX ROWID Object owner=ADM2 Object name=TRANSFER Cost=293 Cardinality=68728 Bytes=1443288
INDEX SKIP SCAN Object owner=ADM2 Object name=IX_TRANSFER_PAYRCVAG Cost=56 Cardinality=508
18 апр 08, 20:10    [5568715]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Landgraf
Member

Откуда:
Сообщений: 278
softwarer
Landgraf

Сколько будет считаться тот же блок, если вместо GetSmt поставить простое выражение, скажем, mod(dt.numberid, 100)?


Ого!! Всего 30 секунд!!!
18 апр 08, 20:22    [5568730]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Landgraf
Member

Откуда:
Сообщений: 278
Попробывал сей час вместо функции select написать! Функция оказалась простой, надо было раньше глянуть :) Время сократилось в 2 раза = 4 минуты! Можно еще как нибудь оптимизировать?


declare
       DateFrom   Date;
       DateTo     Date;
begin
    DateFrom:='01.01.07';
    DateTo:='31.12.07';
    
    For TransfersVolume in (
                              Select Bank, count(*) Kol from
                                    (Select
                                    
                                    (select Id_Bank from BankInfo where Part=DT.NumberID) Bank
                                    From
                                        Transfer DT
                                    Where
                                        DT.Test<>0
                                        DT.Paydate >= DateFrom and
                                        DT.Paydate <= DateTo and
                                        DT.State in (1212, 6565, 2233)
                                    Order by Bank)
                              Group by Bank
                              Order by Kol desc) LOOP
                              
        dbms_output.put_line(TransfersVolume.Bank)||' '||TransfersVolume.Kol); 

    End loop;
end;



18 апр 08, 20:39    [5568754]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Человек и Кошка
Member

Откуда: настоящему индейцу завсегда везде ништяк (с)
Сообщений: 830
Landgraf
Можно еще как нибудь оптимизировать?

Избавьтесь от скаляра:
(select Id_Bank from BankInfo where Part=DT.NumberID) Bank

Спустите BankInfo во from основного запроса
18 апр 08, 20:54    [5568772]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Человек и Кошка
Member

Откуда: настоящему индейцу завсегда везде ништяк (с)
Сообщений: 830
Уберите внутренюю сортировку по Bank, она там бессмысленна...
18 апр 08, 20:56    [5568776]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 63986
Блог
Landgraf
Можно еще как нибудь оптимизировать?

Уберите лишнюю вложенность. Сейчас запрос выглядит форменным заиканием - селект в селекте в селекте ради доступа к одной таблице. Затем снова посмотрите, на что уходит основное время: то ли на чтение, то ли на group by, то ли на order by...
18 апр 08, 22:08    [5569002]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
suPPLer
Member

Откуда: Харків, Україна
Сообщений: 7794
Блог
declare
       DateFrom   Date;
       DateTo     Date;
begin
    DateFrom:='01.01.07';
    DateTo:='31.12.07';
    
    For TransfersVolume in (SELECT Bi.Id_Bank Bank, COUNT(*) Kol FROM Transfer Dt, Bankinfo Bi
                             WHERE Dt.Test <> 0 Dt.Paydate >= Datefrom
                               AND Dt.Paydate <= Dateto
                               AND Dt.State IN (1212, 6565, 2233)
                               AND Bi.Part /*Здесь можно (+) на Ваше усмотрение, Вы данные лучше знаете*/
				     = Dt.Numberid
			     GROUP BY Bank
			     ORDER BY Kol DESC) LOOP
                              
        dbms_output.put_line(TransfersVolume.Bank)||' '||TransfersVolume.Kol); 

    End loop;
end;
18 апр 08, 22:14    [5569013]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация кода  [new]
Landgraf
Member

Откуда:
Сообщений: 278
Всем ОГРОМНЕЙШЕЕ СПАСИБО за ответы!!!
18 апр 08, 23:02    [5569143]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить