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

Откуда:
Сообщений: 219
День добре.

Есть селект вида

select *
from (
        select *
        from (
                 ***
                       select * 
                       from table
                       where условие1
                 ***
              )
        where условиеN-1
       )
where условиеN


соответсвтенно самый внутренний селект отбрасывает наибольшее количество записей из table по условию1, и самый внешний селект отбрасыает по условиюN самое меньшее кол-во записей относительно условия1.
Так вот план запроса выстраивается таким образом что сначала анализируется селект с условиемN, а потом уже с условием1 - стоимость проверки условияN большая - в результате селект делается долго, что сделать?
Спасибо.
12 дек 11, 09:52    [11747068]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
фиганыч,

нужно научиться правильно интерпретировать план запроса.
12 дек 11, 10:00    [11747097]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
фиганыч
Member

Откуда:
Сообщений: 219
mcureenab,

я думаю здесь сложного его неверно интерпретировать

PLAN_TABLE_OUTPUT

------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 278 | 3831 (3)| 00:00:46 |
| 1 | NESTED LOOPS ANTI | | 1 | 278 | 3831 (3)| 00:00:46 |
| 2 | VIEW | | 1 | 265 | 3831 (3)| 00:00:46 |
| 3 | NESTED LOOPS SEMI | | 1 | 83 | 3756 (3)| 00:00:46 |
|* 4 | HASH JOIN ANTI | | 1 | 73 | 3747 (3)| 00:00:45 |
| 5 | NESTED LOOPS | | 1 | 51 | 3744 (3)| 00:00:45 |
| 6 | NESTED LOOPS SEMI | | 1 | 38 | 3738 (3)| 00:00:45 |
| 7 | NESTED LOOPS | | 9 | 234 | 3738 (3)| 00:00:45 |
| 8 | NESTED LOOPS | | 126 | 2016 | 2630 (4)| 00:00:32 |
| 9 | SORT UNIQUE | | 262K| 2823K| 1429 (3)| 00:00:18 |
|* 10 | TABLE ACCESS FULL | CRD_CARD | 262K| 2823K| 1429 (3)| 00:00:18 |
|* 11 | INDEX UNIQUE SCAN | CLI_CLIENT_PK | 1 | 5 | 0 (0)| 00:00:01 |
|* 12 | TABLE ACCESS BY INDEX ROWID| CLI_PROPERTYVALUE | 1 | 12 | 10 (0)| 00:00:01 |
|* 13 | INDEX RANGE SCAN | IDX_CL | 29 | | 3 (0)| 00:00:01 |
|* 14 | TABLE ACCESS BY INDEX ROWID | CLI_PROPERTYVALUE | 1 | 10 | 9 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | IDX_CL | 29 | | 2 (0)| 00:00:01 |
|* 16 | TABLE ACCESS BY INDEX ROWID | CLI_PROPERTYVALUE | 145 | 1740 | 0 (0)| 00:00:01 |
|* 17 | INDEX RANGE SCAN | IDX_CL | 29 | | 2 (0)| 00:00:01 |
|* 18 | VIEW | | 1 | 13 | 6 (0)| 00:00:01 |
| 19 | UNION-ALL | | | | | |
| 20 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 21 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 22 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 23 | TABLE ACCESS FULL | TMP_BIRTHDAYSMS | 1 | 22 | 2 (0)| 00:00:01 |
|* 24 | TABLE ACCESS BY INDEX ROWID | CLI_PROPERTYVALUE | 14464 | 141K| 9 (0)| 00:00:01 |
|* 25 | INDEX RANGE SCAN | IDX_CL | 29 | | 2 (0)| 00:00:01 |
|* 26 | INDEX UNIQUE SCAN | IND_S_SMS_BLOKPHONE_PHONE | 1 | 13 | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------

select *
from (
        select x.id, (select pp.vals from cli_propertyvalue pp where pp.id_cli_client = x.id and pp.id_cli_property = 22) as phone
        from (
                select *
                from (
                        select *
                        from (
                                select x.id, trunc(sysdate,'DDD') - x.d as delta
                                from (
                                        select x.id, to_date(x.mm || '.' || y.yy,'dd.mm.yyyy') as d
                                        from (
                                                select x.id, case when to_char(x.vald,'dd.mm') = '29.02' then '28.02' else to_char(x.vald,'dd.mm') end as mm
                                                from (
                                                        select cl.id, p.vald
                                                        from cli_client cl, cli_propertyvalue p
                                                        where cl.id = p.id_cli_client 
                                                        and p.id_cli_property = 5
                                                        and p.vald is not null) x) x, ( select to_number(to_char(sysdate,'YYYY')) as yy from dual union all -- этот год
                                                                                        select to_number(to_char(sysdate,'YYYY'))-1 as yy from dual union all -- предыдущий год
                                                                                        select to_number(to_char(sysdate,'YYYY'))+1 as yy from dual -- будущий год 
                                                                                        ) y) x) x
                        where delta = 0) x
                where exists(select null from cli_propertyvalue pp where pp.id_cli_client = x.id and pp.id_cli_property in (23,24) and pp.vali = 1)        
                and exists(select null from cli_propertyvalue pp where pp.id_cli_client = x.id and pp.id_cli_property = 12 and pp.vals in ('XXX','YYY'))) x
[color=yellow]       where exists(select null from crd_card ca where ca.id_cli_client = x.id and ca.type = 1 and ca.blok = 0)[/color]
        and not exists(select null from tmp_BirthDaySMS ca where ca.id_cli_client = x.id and trunc(ca.dt,'DDD') = trunc(sysdate,'DDD'))) x
where x.phone is not null
and length(x.phone) = 12
and not exists(select null from S_SMS_BLOKPHONE pp where pp.phone = x.phone)  
12 дек 11, 10:15    [11747151]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
фиганыч
Member

Откуда:
Сообщений: 219
вопрос снят.

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

select id
from (
        select id
        from (
                 ***
                       select id
                       from table
                       where условие1
                 ***
              ) x
        where exists(select /*+INDEX(table1 ID_INDEX)*/null from table1 where table1.id = x.id)
       ) x
where exists(select /*+INDEX(table2 ID_INDEX)*/null from table2 where table2.id = x.id)
12 дек 11, 11:35    [11747755]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
[o_O]
Guest
Непонятно,

зачем ползать в cli_client?
зачем берешь записи за весь год и множишь на три, если в итоге оставляешь только один день?
зачем удалять 29 февраля? чтобы избежать ошибки "ORA-01839 date not valid for month specified"? :)

select p.id_cli_client id
  from cli_propertyvalue p
 where p.id_cli_property = 5
   and to_char(p.vald, 'ddmm') = to_char(sysdate, 'ddmm')

это твой запрос до delta = 0
12 дек 11, 12:08    [11748043]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
фиганыч
Member

Откуда:
Сообщений: 219
[quot [o_O]]
зачем ползать в cli_client?
[/quot]

во избежание отбора не нужных клиентов в случае нарушения целостности

[quot [o_O]]
зачем берешь записи за весь год и множишь на три, если в итоге оставляешь только один день?
[/quot]

селект универсален, и
where delta = 0

в итоге заменится на
where delta = :Param

умножаю на три (текущий, прошлый, следующий год) чтобы избежать потери клиентов, которые родились в граничные даты

[quot [o_O]]
зачем удалять 29 февраля? чтобы избежать ошибки "ORA-01839 date not valid for month specified"? :)
[/quot]

именно :)
14 дек 11, 12:20    [11762918]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6912
to_number(to_char(sysdate,'YYYY'))

по-другому не додумались никак?

case when to_char(x.vald,'dd.mm') = '29.02' then '28.02'

и зачем это? скорее всего оно Вам не надо... наверное LAST_DAY как-то можно прикрутить...
14 дек 11, 17:06    [11766015]     Ответить | Цитировать Сообщить модератору
 Re: План запроса  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6912
alex-ls
case when to_char(x.vald,'dd.mm') = '29.02' then '28.02'

и зачем это? скорее всего оно Вам не надо... наверное LAST_DAY как-то можно прикрутить...

или ADD_MONTHS смотря для чего
14 дек 11, 17:14    [11766112]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить