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

Откуда: Одесса
Сообщений: 846
Есть такой вот запрос с подзапросом. Выполняется 10 секунд к примеру

  with
  acurs   as  
  (
    Select s.r030
    from 
      (select  c1.r030 
      from acurs1 c1
      ) s
    where s.r030 =643
  )
  
    select           
      a.account_num, a.r030,
                   c.r030  as saldo
    from accounts a  
    inner join acurs c on c.r030 = a.r030
    where 
	  a.opendate <= to_date('30.05.2008', 'dd.mm.yyyy')
      and a.closedate >= to_date('30.05.2008', 'dd.mm.yyyy')
      and nvl((select d.saldo
              from dayaccsaldo d
              where d.mfo = a.mfo
                and d.account_id = a.account_id
                and d.operdaydate = 
                  (select max(ss.operdaydate) 
                   from dayaccsaldo ss 
                   where ss.mfo = d.mfo 
                     and ss.account_id = d.account_id 
                     and ss.operdaydate <= to_date('30.05.2008', 'dd.mm.yyyy')
                   )), 0) > 0
      
      and (a.r020 in ('1500','1507')
        or substr(a.r020,1,3) in ('361','364','366')
        or substr(a.r020,1,2) in ('16','19','25','26','27','33'))

Причём сам подзапрос (with...) (отдельно если) выполняется за милисекунду
Если я вместо подзапроса создам табличку

CREATE GLOBAL TEMPORARY TABLE ACURS1
(
  R030  CHAR(3 BYTE)
)
ON COMMIT PRESERVE ROWS
NOCACHE;

Внесу туда несколько значений, одно из которых 643, то такой вот запрос
    select           
      a.account_num, a.r030,
                   c.r030  as saldo
    from accounts a  
    inner join acurs1 c on c.r030 = a.r030
    where 
	  a.opendate <= to_date('30.05.2008', 'dd.mm.yyyy')
      and a.closedate >= to_date('30.05.2008', 'dd.mm.yyyy')
      and nvl((select d.saldo
              from dayaccsaldo d
              where d.mfo = a.mfo
                and d.account_id = a.account_id
                and d.operdaydate = 
                  (select max(ss.operdaydate) 
                   from dayaccsaldo ss 
                   where ss.mfo = d.mfo 
                     and ss.account_id = d.account_id 
                     and ss.operdaydate <= to_date('30.05.2008', 'dd.mm.yyyy')
                   )), 0) > 0
      
      and (a.r020 in ('1500','1507')
        or substr(a.r020,1,3) in ('361','364','366')
        or substr(a.r020,1,2) in ('16','19','25','26','27','33'))

выполняется намного меньше секунды. Изменилось тут то, что я убрал подзапрос и в inner join вместо него указал темповую табличку.
Что это может быть за фиговина такая?

Вот план тормознутого запроса:
Operation	Object Name	Rows	Bytes	Cost	Object Node	In/Out	PStart	PStop

SELECT STATEMENT Optimizer Mode=ALL_ROWS		458  	 	663  	 	      	             	 
  FILTER		  	 	 	 	      	             	 
    HASH JOIN		458  	25 K	639  	 	      	             	 
      TABLE ACCESS FULL	ODB_STAT.ACURS1	1  	5  	2  	 	      	             	 
      TABLE ACCESS FULL	ODB_STAT.ACCOUNTS	14 K	721 K	637  	 	      	             	 
    FILTER		  	 	 	 	      	             	 
      HASH GROUP BY		1  	69  	24  	 	      	             	 
        HASH JOIN		1  	69  	23  	 	      	             	 
          INDEX RANGE SCAN	ODB_STAT.PK_DAYACCSALDO	16  	512  	3  	 	      	             	 
          TABLE ACCESS BY INDEX ROWID	ODB_STAT.DAYACCSALDO	16  	592  	19  	 	      	             	 
            INDEX RANGE SCAN	ODB_STAT.PK_DAYACCSALDO	16  	 	3  	 	      	             	 

А вот нормального

Operation	Object Name	Rows	Bytes	Cost	Object Node	In/Out	PStart	PStop

SELECT STATEMENT Optimizer Mode=ALL_ROWS		1 K	 	659  	 	      	             	 
  FILTER		  	 	 	 	      	             	 
    HASH JOIN		1 K	76 K	639  	 	      	             	 
      TABLE ACCESS FULL	ODB_STAT.ACURS1	3  	15  	2  	 	      	             	 
      TABLE ACCESS FULL	ODB_STAT.ACCOUNTS	14 K	721 K	637  	 	      	             	 
    NESTED LOOPS		1  	55  	20  	 	      	             	 
      VIEW	SYS.VW_SQ_1	16  	480  	3  	 	      	             	 
        SORT GROUP BY		16  	512  	3  	 	      	             	 
          INDEX RANGE SCAN	ODB_STAT.PK_DAYACCSALDO	16  	512  	3  	 	      	             	 
      TABLE ACCESS BY INDEX ROWID	ODB_STAT.DAYACCSALDO	1  	25  	2  	 	      	             	 
        INDEX UNIQUE SCAN	ODB_STAT.PK_DAYACCSALDO	1  	 	1  	 	      	             	 


Suse Sles 9 SP3 64 bit + Oracle 10.2.0.3 64 bit
5 июн 08, 19:31    [5767124]     Ответить | Цитировать Сообщить модератору
 Re: Подзапрос тормозит запрос  [new]
stax..
Guest
посмотрите на планы с помощью dbms_xplan

самое простое сделать запрос "нераскриваемым"
добавіть hint или банально rownum<874763535623
.....
stax
5 июн 08, 21:38    [5767433]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить