powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / STOPKEY после PARTITION RANGE ITERATOR при динамическом partition pruning
3 сообщений из 3, страница 1 из 1
STOPKEY после PARTITION RANGE ITERATOR при динамическом partition pruning
    #39964208
Akustik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть: таблица с range (ну или interval) партиционированием по дате.
Нужно найти первую строку начиная с самой поздней партиции с заданными границами по дате партиционирования.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create table test_pruning(d)
partition by range(d)(
 partition p1 values less than (date '2020-01-11'),
 partition p2 values less than (date '2020-01-12'),
 partition p3 values less than (date '2020-01-13'),
 partition p4 values less than (date '2020-01-14'))
as
select date '2020-01-10' from dual union all
select date '2020-01-11' from dual union all
select date '2020-01-12' from dual union all
select date '2020-01-13' from dual;
commit;



Если никаких фильтров на дату партиционирования нет, то всё хорошо - STOPKEY идёт сразу после TABLE ACCESS и до PARTITION RANGE ALL:
Код: plsql
1.
2.
3.
4.
5.
select /*+gather_plan_statistics*/*
  from (select *
          from test_pruning t
      order by d desc)
 where rownum = 1;


Что получили:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name         | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |
----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |              |      1 |        |       |    17 (100)|          |       |       |      1 |
|*  1 |  COUNT STOPKEY           |              |      1 |        |       |            |          |       |       |      1 |
|   2 |   PARTITION RANGE ALL    |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |     4 |     1 |      1 |
|   3 |    VIEW                  |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|*  4 |     SORT ORDER BY STOPKEY|              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|   5 |      TABLE ACCESS FULL   | TEST_PRUNING |      1 |      5 |    45 |    16   (0)| 00:00:01 |     4 |     1 |      1 |
----------------------------------------------------------------------------------------------------------------------------


Начали сканить с 4й по 1ю партицию, но просканили только одну, нашли 1 строку и закончили. Благодаря тому что STOPKEY находится под PARTITION RANGE ALL

Если задать только правую границу, то тоже всё хорошо:
Код: plsql
1.
2.
3.
4.
5.
6.
select /*+gather_plan_statistics*/*
  from (select *
          from test_pruning t
         where d <= :d_2020_01_12
      order by d desc)
 where rownum = 1;


Получили:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name         | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |              |      1 |        |       |    17 (100)|          |       |       |      1 |
|*  1 |  COUNT STOPKEY            |              |      1 |        |       |            |          |       |       |      1 |
|   2 |   PARTITION RANGE ITERATOR|              |      1 |      5 |    45 |    17   (6)| 00:00:01 |   KEY |     1 |      1 |
|   3 |    VIEW                   |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|*  4 |     SORT ORDER BY STOPKEY |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|*  5 |      TABLE ACCESS FULL    | TEST_PRUNING |      1 |      5 |    45 |    16   (0)| 00:00:01 |   KEY |     1 |      1 |
-----------------------------------------------------------------------------------------------------------------------------


в общем-то, всё также, только теперь сканим не с 4й, а с вычисленной партиции, всё логично.
С заданной только левой границей всё тоже самое, всё ожидаемо.

А вот с обеими заданными границами начинаются проблемы:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select /*+gather_plan_statistics*/*
  from (select *
          from test_pruning t
         where d >= :d_2020_01_11
           and d <= :d_2020_01_12
      order by d desc)
 where rownum = 1;


и получили лажу:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |      1 |        |       |    17 (100)|          |       |       |      1 |
|*  1 |  COUNT STOPKEY               |              |      1 |        |       |            |          |       |       |      1 |
|   2 |   VIEW                       |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|*  3 |    SORT ORDER BY STOPKEY     |              |      1 |      5 |    45 |    17   (6)| 00:00:01 |       |       |      1 |
|*  4 |     FILTER                   |              |      1 |        |       |            |          |       |       |      2 |
|   5 |      PARTITION RANGE ITERATOR|              |      1 |      5 |    45 |    16   (0)| 00:00:01 |   KEY |   KEY |      2 |
|*  6 |       TABLE ACCESS FULL      | TEST_PRUNING |      2 |      5 |    45 |    16   (0)| 00:00:01 |   KEY |   KEY |      2 |
--------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(ROWNUM=1)
   3 - filter(ROWNUM=1)
   4 - filter(:D_2020_01_12>=:D_2020_01_11)
   6 - filter(("D">=:D_2020_01_11 AND "D"<=:D_2020_01_12))


STOPKEY теперь делается после PARTITION RANGE ITERATOR. Это приводит к тому что сканим 2 партиции, получаем 2 строки.
Не понимаю, каким образом тут мешает (и мешает ли) появившийся фильтр(4) валидиции границ (правая >= левой) - :D_2020_01_12>=:D_2020_01_11

Подобное обсуждали вот тут , а прям конкретно эта проблема вот там (предложили написать d+0 >=, но это ерунда потому что ломает прунинг по левой границе).
Что делать, неясно. Есть мысли?

P.S. Проблема только с биндами - с литералами всё прекрасно.
P.P.S. Тесткейс упростил максимально (в сравнении с бизнес задачей). Возможно, даже слишком - усложню, если нужно.
P.P.P.S. 11.2, 19c - одинаково плохо.
...
Рейтинг: 0 / 0
STOPKEY после PARTITION RANGE ITERATOR при динамическом partition pruning
    #39964255
Alexander Anokhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
На мой взгляд это баг. Оптимизатор не видит, что в случае KEY/KEY партиции в PARTITION RANGE ITERATOR будут сканироваться по порядку, согласно сортировке.

Workarounds:
Код: plsql
1.
_optimizer_filter_pushdown = false

или
Код: plsql
1.
_optimizer_generate_transitive_pred = false 


в сессии или хинтом, например,
Код: plsql
1.
/*+ opt_param('_optimizer_filter_pushdown', 'false') */


Либо можно создать локальный индекс on TEST_PRUNING(d), чтобы вообще от сортировки избавиться.
...
Рейтинг: 0 / 0
STOPKEY после PARTITION RANGE ITERATOR при динамическом partition pruning
    #39964262
Akustik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexander Anokhin,

_optimizer_filter_pushdown помог, спасибо.
фильтр на границы пропал и STOPKEY вернулся на место. пойду почитаю, что это такое.
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / STOPKEY после PARTITION RANGE ITERATOR при динамическом partition pruning
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]