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

Откуда:
Сообщений: 1909
В 10.2 наткнулся на незнакомую операцию в плане.

PARTITION RANGE (OR)

Кто-нибудь встречал описание?
3 авг 06, 19:58    [2962328]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
DВА
Member

Откуда:
Сообщений: 5439
http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14223/parpart.htm

Another example using advanced pruning is the following, which uses an OR predicate:

SELECT p.promo_name promo_name, (s.profit - p.promo_cost) profit
FROM
promotions p,
(SELECT
promo_id,
SUM(sales.QUANTITY_SOLD * (costs.UNIT_PRICE - costs.UNIT_COST)) profit
FROM
sales, costs
WHERE
((sales.time_id BETWEEN TO_DATE('01-JAN-1998','DD-MON-YYYY',
'NLS_DATE_LANGUAGE = American') AND
TO_DATE('01-JAN-1999','DD-MON-YYYY', 'NLS_DATE_LANGUAGE = American')
OR
(sales.time_id BETWEEN TO_DATE('01-JAN-2001','DD-MON-YYYY',
'NLS_DATE_LANGUAGE = American') AND
TO_DATE('01-JAN-2002','DD-MON-YYYY', 'NLS_DATE_LANGUAGE = American')))
AND sales.time_id = costs.time_id
AND sales.prod_id = costs.prod_id
GROUP BY
promo_id) s
WHERE s.promo_id = p.promo_id
ORDER BY profit
DESC;

This query joins the sales and costs tables in the sh sample schema. The sales
table is partitioned by range on the column time_id. One of the conditions in the
query are two predicates on time_id, which are combined with an OR operator.
This OR predicate is used to prune the partitions in sales table and a single join
between sales and costs table is performed. The plan is as follows:


--------------------------------------------------------------------------------------------------
| Id| Operation | Name |Rows |Bytes |TmpSp|Cost(%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 4 | 200 | | 3556 (14)| 00:00:43| | |
| 1| SORT ORDER BY | | 4 | 200 | | 3556 (14)| 00:00:43| | |
|* 2| HASH JOIN | | 4 | 200 | | 3555 (14)| 00:00:43| | |
| 3| TABLE ACCESS FULL |PROMOTIONS| 503 | 16599| | 16 (0)| 00:00:01| | |
| 4| VIEW | | 4 | 68 | | 3538 (14)| 00:00:43| | |
| 5| HASH GROUP BY | | 4 | 164 | | 3538 (14)| 00:00:43| | |
| 6| PARTITION RANGE OR | | 314K| 12M| | 3321 (9)| 00:00:40|KEY(OR)|KEY(OR)|
|* 7| HASH JOIN | | 314K| 12M| 440K| 3321 (9)| 00:00:40| | |
|* 8| TABLE ACCESS FULL| SALES | 402K| 7467K| | 400 (39)| 00:00:05|KEY(OR)|KEY(OR)|
| 9| TABLE ACCESS FULL | COSTS |82112| 1764K| | 77 (24)| 00:00:01|KEY(OR)|KEY(OR)|
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("S"."PROMO_ID"="P"."PROMO_ID")
7 - access("SALES"."TIME_ID"="COSTS"."TIME_ID" AND "SALES"."PROD_ID"="COSTS"."PROD_ID")
8 - filter("SALES"."TIME_ID"<=TO_DATE('1999-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
"SALES"."TIME_ID">=TO_DATE('1998-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
"SALES"."TIME_ID">=TO_DATE('2001-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
"SALES"."TIME_ID"<=TO_DATE('2002-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))

3 авг 06, 20:30    [2962404]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
contr
Member

Откуда:
Сообщений: 1909
Ната, спасибо, это я и сам раскопал :)
Меня интересует механика и ограничения.
3 авг 06, 20:33    [2962421]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10051
Empirically: OR of single values produces INLIST:

SQL> explain plan for
  2  select * from range_sales where time_id = TO_DATE('01-APR-1999','DD-MON-YYYY')
  3  or time_id = TO_DATE('01-APR-1998','DD-MON-YYYY');

Explained.

SQL> @?\rdbms\admin\utlxpls

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2564953587

----------------------------------------------------------------------------------------------------
| Id  | Operation              | Name        | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |             |     1 |    77 |     2   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE INLIST|             |     1 |    77 |     2   (0)| 00:00:01 |KEY(I) |KEY(I) |
|*  2 |   TABLE ACCESS FULL    | RANGE_SALES |     1 |    77 |     2   (0)| 00:00:01 |KEY(I) |KEY(I) |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - filter("TIME_ID"=TO_DATE('1998-04-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "TIME_ID"=TO_DATE('1999-04-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))

Note
-----
   - dynamic sampling used for this statement

19 rows selected.

If at least one of OR'ed conditions is a range:

SQL> explain plan for
  2  select * from range_sales where time_id >= TO_DATE('01-APR-1999','DD-MON-YYYY')
  3  or time_id = TO_DATE('01-APR-1998','DD-MON-YYYY');

Explained.

SQL> @?\rdbms\admin\utlxpls

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 3936216512

--------------------------------------------------------------------------------------------------
| Id  | Operation          | Name        | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |             |     1 |    77 |     2   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE OR|             |     1 |    77 |     2   (0)| 00:00:01 |KEY(OR)|KEY(OR)|
|*  2 |   TABLE ACCESS FULL| RANGE_SALES |     1 |    77 |     2   (0)| 00:00:01 |KEY(OR)|KEY(OR)|
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - filter("TIME_ID">=TO_DATE('1999-04-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') OR
              "TIME_ID"=TO_DATE('1998-04-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))

Note
-----
   - dynamic sampling used for this statement

19 rows selected.

SY.
3 авг 06, 20:56    [2962490]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
contr
Member

Откуда:
Сообщений: 1909
SY
Empirically: OR of single values produces INLIST:

Спасибо SY, но эмпирически я тоже это все вообразил и подкрепил догадки экспериментами.
Интересно в первую голову подтверждение этой эмпирики "де-юре", т.е. подробное описание механизма и его ограничений от Oracle или хотя бы от Oracle Experts.
Я не могу пускать в production эмпирику :)
3 авг 06, 22:55    [2962801]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10051
Unfortunately, подробное описание механизма и его ограничений and CBO is an oxymoron.

SY.
3 авг 06, 23:09    [2962836]     Ответить | Цитировать Сообщить модератору
 Re: Незнакомая операция в плане  [new]
contr
Member

Откуда:
Сообщений: 1909
Why "oxymoron"?
Это совершенно параллельные вселенные :)
3 авг 06, 23:36    [2962892]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить