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

Откуда: Москва
Сообщений: 955
Всем добрый день. Имеется такой запрос:

SELECT /*+USE_MERGE(A,B)*/
		B.SERIAL_NUMBER,
		B.TEXT_VALUE DEFECT
FROM
	(SELECT
			SERIAL_NUMBER,
			TEXT_VALUE,
			CREATION_TIME
	FROM
		(SELECT
			ROW_NUMBER() OVER(PARTITION BY SERIAL_NUMBER ORDER BY CREATION_TIME DESC) RNK,
			SERIAL_NUMBER,
			TEXT_VALUE,
			CREATION_TIME
		FROM
			IDP_SERIAL_NUMBER_CHARS
		WHERE
			CREATION_TIME BETWEEN (SYSDATE-INTERVAL '1' MONTH) AND (SYSDATE)
			AND ARM_NUMBER='6'
			AND TSD_OPERATION='10'
		) AA
		WHERE
			RNK=1
			AND TEXT_VALUE='22222'
	) A
	JOIN
	(SELECT
			SERIAL_NUMBER,
			TEXT_VALUE,
			CREATION_TIME
	FROM
		IDP_SERIAL_NUMBER_CHARS
	WHERE
		CREATION_TIME BETWEEN (SYSDATE-INTERVAL '1' MONTH) AND (SYSDATE)
		AND TEXT_VALUE<>'22222'
		AND ARM_NUMBER='6'
		AND TSD_OPERATION='27'
	) B
	ON A.SERIAL_NUMBER=B.SERIAL_NUMBER

а вот его план:

Plan
SELECT STATEMENT  CHOOSECost: 9  Bytes: 154  Cardinality: 1  IO Cost: 9  							
	10 FILTER  Filter Predicates: SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH<=SYSDATE@!  						
		9 MERGE JOIN  Cost: 9  Bytes: 154  Cardinality: 1  IO Cost: 9  					
			5 VIEW FIN_NKSH. Object Instance: 2  Filter Predicates: "AA"."RNK"=1 AND "AA"."TEXT_VALUE"='22222'  Cost: 5  Bytes: 67  Cardinality: 1  				
				4 WINDOW SORT PUSHED RANK  Filter Predicates: ROW_NUMBER() OVER ( PARTITION BY "IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER" ORDER BY "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME" DESC )<=1  Cost: 5  Bytes: 87  Cardinality: 1  IO Cost: 5  			
					3 FILTER  Filter Predicates: SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH<=SYSDATE@!  		
						2 TABLE ACCESS BY INDEX ROWID FIN_NKSH.IDP_SERIAL_NUMBER_CHARS Object Instance: 3  Cost: 3  Bytes: 87  Cardinality: 1  IO Cost: 3  	
							1 INDEX RANGE SCAN NON-UNIQUE FIN_NKSH.IDP_SERIAL_NUMBER_CHARS_IDX1 Search Columns: 3  Access Predicates: "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME">=SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH AND "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPERATION"='10' AND "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME"<=SYSDATE@!  Filter Predicates: "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPERATION"='10'  Cost: 2  Cardinality: 1,687  IO Cost: 2  
			8 SORT JOIN  Access Predicates: "AA"."SERIAL_NUMBER"="IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER"  Filter Predicates: "AA"."SERIAL_NUMBER"="IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER"  Cost: 5  Bytes: 87  Cardinality: 1  IO Cost: 5  				
				7 TABLE ACCESS BY INDEX ROWID FIN_NKSH.IDP_SERIAL_NUMBER_CHARS Object Instance: 5  Cost: 3  Bytes: 87  Cardinality: 1  IO Cost: 3  			
					6 INDEX RANGE SCAN NON-UNIQUE FIN_NKSH.IDP_SERIAL_NUMBER_CHARS_IDX1 Search Columns: 3  Access Predicates: "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME">=SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH AND "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPERATION"='27' AND "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME"<=SYSDATE@!  Filter Predicates: "IDP_SERIAL_NUMBER_CHARS"."TEXT_VALUE"<>'22222' AND "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPERATION"='27'  Cost: 2  Cardinality: 84  IO Cost: 2  		

Индекс на таблице:
CREATE INDEX IDP_SERIAL_NUMBER_CHARS_IDX1 ON IDP_SERIAL_NUMBER_CHARS(CREATION_TIME,ARM_NUMBER,TSD_OPERATION,TEXT_VALUE);

Ставит в тупик один момент: почему фильтрация для второго подзапроса по времени осуществляется в самом конце, а не до соединения результатов подзапросов (судя по плану).
Мне кажется эффективней будет сначала отфильтровать, а потом уже соединять, т.к. нужно будет сортировать гораздо меньшее количество строк.
Можно ли как то хинтом принудительно заставить полностью фильтровать подзапросы до соединения.
И вообще, почему так происходит?
19 май 09, 16:14    [7199274]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
Timm
Member

Откуда: Moscow, Ё-burg
Сообщений: 3696
Покажи нормальный человеческий план через dbms_xplan.
19 май 09, 16:25    [7199375]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
Elic
Member

Откуда:
Сообщений: 29991
publexus
почему фильтрация для второго подзапроса по времени осуществляется в самом конце, а не до соединения результатов подзапросов (судя по плану).
Ты не умеешь "судить".
19 май 09, 16:26    [7199384]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
publexus
Member

Откуда: Москва
Сообщений: 955
Elic
publexus
почему фильтрация для второго подзапроса по времени осуществляется в самом конце, а не до соединения результатов подзапросов (судя по плану).
Ты не умеешь "судить".

Ну а почему тогда у этой операции самый последний номер (10)? Разве это не порядок выполнения операций?
19 май 09, 16:32    [7199426]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
publexus
Member

Откуда: Москва
Сообщений: 955
Timm
Покажи нормальный человеческий план через dbms_xplan.

Показываю:

PLAN_TABLE_OUTPUT

 
--------------------------------------------------------------------------------------------------
| Id  | Operation                        |  Name                         | Rows  | Bytes | Cost  |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                               |     1 |   154 |     9 |
|*  1 |  FILTER                          |                               |       |       |       |
|   2 |   MERGE JOIN                     |                               |     1 |   154 |     9 |
|*  3 |    VIEW                          |                               |     1 |    67 |     5 |
|*  4 |     WINDOW SORT PUSHED RANK      |                               |     1 |    87 |     5 |
|*  5 |      FILTER                      |                               |       |       |       |
|   6 |       TABLE ACCESS BY INDEX ROWID| IDP_SERIAL_NUMBER_CHARS       |     1 |    87 |     3 |
|*  7 |        INDEX RANGE SCAN          | IDP_SERIAL_NUMBER_CHARS_IDX1  |  1687 |       |     2 |
|*  8 |    SORT JOIN                     |                               |     1 |    87 |     5 |
|   9 |     TABLE ACCESS BY INDEX ROWID  | IDP_SERIAL_NUMBER_CHARS       |     1 |    87 |     3 |
|* 10 |      INDEX RANGE SCAN            | IDP_SERIAL_NUMBER_CHARS_IDX1  |    84 |       |     2 |
--------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH<=SYSDATE@!)
   3 - filter("AA"."RNK"=1 AND "AA"."TEXT_VALUE"='22222')
   4 - filter(ROW_NUMBER() OVER ( PARTITION BY "IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER" ORDER 
              BY "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME" DESC )<=1)
   5 - filter(SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO MONTH<=SYSDATE@!)
   7 - access("IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME">=SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO 
              MONTH AND "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS 
              "."TSD_OPERATION"='10' AND "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME"<=SYSDATE@! 
       filter("IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPE
              RATION"='10')
   8 - access("AA"."SERIAL_NUMBER"="IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER")
       filter("AA"."SERIAL_NUMBER"="IDP_SERIAL_NUMBER_CHARS"."SERIAL_NUMBER")
  10 - access("IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME">=SYSDATE@!-INTERVAL'+00-01' YEAR(2) TO 
              MONTH AND "IDP_SERIAL_NUMBER_CHARS"."ARM_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS 
              "."TSD_OPERATION"='27' AND "IDP_SERIAL_NUMBER_CHARS"."CREATION_TIME"<=SYSDATE@! 
       filter("IDP_SERIAL_NUMBER_CHARS"."TEXT_VALUE"<>'22222' AND "IDP_SERIAL_NUMBER_CHARS"."AR
              M_NUMBER"='6' AND "IDP_SERIAL_NUMBER_CHARS"."TSD_OPERATION"='27')
 
Note: cpu costing is off
19 май 09, 16:39    [7199482]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
Elic
Member

Откуда:
Сообщений: 29991
publexus
Ну а почему тогда у этой операции самый последний номер (10)? Разве это не порядок выполнения операций?
Этот фильтр выполняется самым первым и всего лишь раз, чтобы глубже даже не заходить. Если ты обратишь внимание, то там проверяется, что начало интервала не больше конца :)
19 май 09, 16:53    [7199600]     Ответить | Цитировать Сообщить модератору
 Re: Почему фильтрация выносится из подзапроса во внешний запрос  [new]
publexus
Member

Откуда: Москва
Сообщений: 955
Elic
publexus
Ну а почему тогда у этой операции самый последний номер (10)? Разве это не порядок выполнения операций?
Этот фильтр выполняется самым первым и всего лишь раз, чтобы глубже даже не заходить. Если ты обратишь внимание, то там проверяется, что начало интервала не больше конца :)

ОК. Кажется начинаю понимать, все стало более или менее ясно.
19 май 09, 17:07    [7199734]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить