Информация об изменениях

Сообщение Re[2]: Oracle еше одна проблема. чтоб им. от 28.04.2015 15:44

Изменено 28.04.2015 15:58 MasterZiv

Здравствуйте, зиг, Вы писали:

зиг>>Итак, проблема следующая. есть Запрос, который работает медленно если в первый раз запускаешь. Вторые и последующие запуски (даже с изменением параметров запроса) уже более-менее быстрые — то есть видать что-то там оракл кладет в кэш. Хотелось бы чтоб запрос работал более стабильно!

зиг>>План вообще какой-то неинформативный как по мне — кост очень небольшой. То есть непонятно что там улучшать, оно типа и так все хорошо.

Так в чём проблема-то? Если только в этом, т.е. "кэш-не кэш" -- это вообще не проблема, и разговаривать не о чем.

О запросе и плане -- запрос непростой, и в него надо вникать, так сходу ничего не понятно, и надо знать данные и их
распределение, естественно.
Вот кстати он немного более аккуратно сформатированный:

[code SQL]
select B.* from
(select A.*, rownum as rn from
(select C.COMPANYNAME, C.COMPANYID as CLIENT, P.INSTRUMENT, P.VALID_FROM, P.FREQUENCY, P.DETAILEDFREQUENCY, cf.VAL_DATE ,
(select max(vv.val_date)
from tableE vv
where vv.REQUEST = p.PKEY and vv.VALID = 'Y' and vv.dealer=8
) as ASOF
from tableN c
inner join tableD dp on c.companyId=dp.companyId and dp.dealer=8
inner join tableC p on p.VALID = 'Y' and p.SINGLE = 'Y' and p.OWNER = c.COMPANYID
inner join VM_CALENDAR_FREQUENCIES cf on cf.FREQUENCY=p.FREQUENCY and cf.DETAILEDFREQUENCY=p.DETAILEDFREQUENCY and cf.VAL_DATE between '20150427' and '20150427' and cf.REGIONALHUB in ('ALL',c.REGIONALHUB)
inner join VM_IDS i on i.ID_KEY = P.INSTRUMENT and i.VALID = 'Y'
inner join tableA b on i.BOND = b.PKEY and b.VALID = 'Y'
inner join tableB_DEFAULT_PERMS pd on pd.dealer=12584 and pd.VALID ='Y' and
(pd.START_DATE is null or '20150427' > pd.START_DATE) and(pd.END_DATE is null or '20150727' < pd.END_DATE)
and pd.client=p.owner and ( (pd.bond_type=b.type and pd.bond_type in ('Sov','Corp','StatBody'))
or ( pd.bond_type = 'Unclassified' and (b.type not in ('Sov','Corp','StatBody') or b.type is null ) )
)
left outer join tableB_REQUEST_PERMS pm on pm.instrument = p.instrument and pm.CLIENT = p.owner
and pm.DEALER = 12584
and pm.VALID = 'Y'
and pm.request_id=p.pkey
and (pm.START_DATE is null or '20150427' > pm.START_DATE)
and(pm.END_DATE is null or '20150427' < pm.END_DATE)
where (c.ISCURRENT = 'Y' and c.ISDEALER = 'N' and c.REGIONALHUB in ('BLA', 'BLU', 'BLE', 'BBB', 'YY'))
and ((pm.permission in ('A','B','M','Y') )
or ( (pm.permission is null or pm.permission ='P') and (pd.permission in ('A','B','M','Y') ) )
)
order by c.COMPANYNAME Asc nulls first, c.COMPANYNAME, cf.VAL_DATE asc ) A
where rownum <= 30) B
where rn > 1;
[/code]

Очевидно, что в нём много альтернативных вариантов выполнения, от них нужно избавляться -- выполнять несколько разных запросов в разных случаях.
Также строковые литералы дат нужно оборачивать в to_date( но это к производительности не относится).

SARG-и только c.ISCURRENT = 'Y' and c.ISDEALER = 'N' and c.REGIONALHUB in ('BLA', 'BLU', 'BLE', 'BBB', 'YY')
Если они отбирают мало записей, то надо на них строить индексы и всё ОК,
если много -- ну, значит запрос такой.

Ну и ещё я бы уплощил бы запрос (убрал ненужные тут вложенные запросы ) или это пейджинг такой делается ? Тогда его надо на клиенте делать, а не так.
Если это не пейджинг, а аналитика, то для неё строк-то маловато, у тебя там HASH JOIN светится в куске плана -- это для 30 строк накладно,
тут можно ORDER индексом попробовать оптимизировать, и получать только 30 записей (ну или чуть больше).


зиг>ну то есть какой помощи от вас я прошу. не чтоб вы мне тут запрос переписали, или с индексами помогли — понятно что это невозможно без всех знаний всех таблиц и всего что там находится.

зиг>мне нужен совет — в каком направлении пнуть наших DBA которые базу майнтейнят. может быть тут очевидная какая-то недоработка с их стороны? типа если кост запроса небольшой а фактически выполняется он долго — значит , я не знаю, статистика там хреново обновляется например. или что-нибудь аналогичное же.
зиг>если б хотя бы план отображал действительную картину — тогда было бы уже легче инвестигировать. то есть я так понимаю проблему надо начинать решать с этой стороны?

Не похоже. Т.е. даже если статистика плоха, ты можешь всобачить HINT и статистика будет уже по-боку.
Явно тут напрашивается хинт first_rows(30), тогда может HASH JOIN уйдёт. Но надо весь план смотреть.

И сколько запрос работает в итоге ?
Re[2]: Oracle еше одна проблема. чтоб им.
Здравствуйте, зиг, Вы писали:

зиг>>Итак, проблема следующая. есть Запрос, который работает медленно если в первый раз запускаешь. Вторые и последующие запуски (даже с изменением параметров запроса) уже более-менее быстрые — то есть видать что-то там оракл кладет в кэш. Хотелось бы чтоб запрос работал более стабильно!

зиг>>План вообще какой-то неинформативный как по мне — кост очень небольшой. То есть непонятно что там улучшать, оно типа и так все хорошо.

Так в чём проблема-то? Если только в этом, т.е. "кэш-не кэш" -- это вообще не проблема, и разговаривать не о чем.

О запросе и плане -- запрос непростой, и в него надо вникать, так сходу ничего не понятно, и надо знать данные и их
распределение, естественно.
Вот кстати он немного более аккуратно сформатированный:

select B.* from 
(select A.*, rownum as rn  from 
     (select  C.COMPANYNAME, C.COMPANYID as CLIENT, P.INSTRUMENT, P.VALID_FROM, P.FREQUENCY, P.DETAILEDFREQUENCY, cf.VAL_DATE ,
              (select max(vv.val_date)        
              from tableE vv
              where vv.REQUEST = p.PKEY and vv.VALID = 'Y' and vv.dealer=8
              ) as ASOF  
      from tableN c
       inner join tableD dp on c.companyId=dp.companyId and dp.dealer=8
       inner join tableC p on p.VALID = 'Y' and p.SINGLE = 'Y' and  p.OWNER = c.COMPANYID
       inner join VM_CALENDAR_FREQUENCIES cf on cf.FREQUENCY=p.FREQUENCY and cf.DETAILEDFREQUENCY=p.DETAILEDFREQUENCY and cf.VAL_DATE between '20150427' and '20150427' and cf.REGIONALHUB in ('ALL',c.REGIONALHUB)
       inner join VM_IDS i on i.ID_KEY = P.INSTRUMENT and i.VALID = 'Y'
       inner join tableA b on i.BOND = b.PKEY and b.VALID = 'Y'
       inner join tableB_DEFAULT_PERMS pd on pd.dealer=12584 and pd.VALID ='Y' and
              (pd.START_DATE is null or '20150427' > pd.START_DATE) and(pd.END_DATE is null or '20150727' < pd.END_DATE)
              and pd.client=p.owner and ( (pd.bond_type=b.type and pd.bond_type in ('Sov','Corp','StatBody')) 
                                         or (  pd.bond_type = 'Unclassified' and (b.type not in ('Sov','Corp','StatBody')  or b.type is null ) ) 
                                         )  
       left outer join tableB_REQUEST_PERMS pm on pm.instrument = p.instrument and pm.CLIENT = p.owner
                                                  and pm.DEALER = 12584 
                                                  and pm.VALID = 'Y' 
                                                  and pm.request_id=p.pkey  
                                                  and (pm.START_DATE is null or '20150427' > pm.START_DATE) 
                                                  and(pm.END_DATE is null or '20150427' < pm.END_DATE) 
        where (c.ISCURRENT = 'Y' and c.ISDEALER = 'N' and c.REGIONALHUB in ('BLA', 'BLU', 'BLE', 'BBB', 'YY')) 
        and ((pm.permission in ('A','B','M','Y') ) 
             or ( (pm.permission is null or pm.permission ='P') and (pd.permission in ('A','B','M','Y') ) )
            ) 
        order by c.COMPANYNAME Asc nulls first, c.COMPANYNAME, cf.VAL_DATE asc ) A  
  where rownum <= 30) B  
where  rn > 1;


Очевидно, что в нём много альтернативных вариантов выполнения, от них нужно избавляться -- выполнять несколько разных запросов в разных случаях.
Также строковые литералы дат нужно оборачивать в to_date( но это к производительности не относится).

SARG-и только c.ISCURRENT = 'Y' and c.ISDEALER = 'N' and c.REGIONALHUB in ('BLA', 'BLU', 'BLE', 'BBB', 'YY')
Если они отбирают мало записей, то надо на них строить индексы и всё ОК,
если много -- ну, значит запрос такой.

Ну и ещё я бы уплощил бы запрос (убрал ненужные тут вложенные запросы ) или это пейджинг такой делается ? Тогда его надо на клиенте делать, а не так.
Если это не пейджинг, а аналитика, то для неё строк-то маловато, у тебя там HASH JOIN светится в куске плана -- это для 30 строк накладно,
тут можно ORDER индексом попробовать оптимизировать, и получать только 30 записей (ну или чуть больше).


зиг>ну то есть какой помощи от вас я прошу. не чтоб вы мне тут запрос переписали, или с индексами помогли — понятно что это невозможно без всех знаний всех таблиц и всего что там находится.

зиг>мне нужен совет — в каком направлении пнуть наших DBA которые базу майнтейнят. может быть тут очевидная какая-то недоработка с их стороны? типа если кост запроса небольшой а фактически выполняется он долго — значит , я не знаю, статистика там хреново обновляется например. или что-нибудь аналогичное же.
зиг>если б хотя бы план отображал действительную картину — тогда было бы уже легче инвестигировать. то есть я так понимаю проблему надо начинать решать с этой стороны?

Не похоже. Т.е. даже если статистика плоха, ты можешь всобачить HINT и статистика будет уже по-боку.
Явно тут напрашивается хинт first_rows(30), тогда может HASH JOIN уйдёт. Но надо весь план смотреть.

И сколько запрос работает в итоге ?