powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Cкан партиционированной таблицы медленнее непарциционированной.
25 сообщений из 47, страница 1 из 2
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322606
yon_brover
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На первом сервере имеется таблица изменений остатков по счетам за последние 20 лет:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
create table LIM
(
  PRODATE      DATE not null, -- дата остатка
  ACC          VARCHAR2(10) not null, -- номер счёта
  CURRCODE     VARCHAR2(3) not null, -- валюта счёта
  LIM          NUMBER -- остаток по счёту
);



Есть индекс для определения остатка по счёту на дату:

Код: plsql
1.
create unique index LIM on LIM (ACC, CURRCODE, PRODATE);



Запрашиваем дату последнего изменения остатка по счёту:

Код: plsql
1.
select max(prodate) from lim where acc = '014654567 ' and currcode = '000';



Мгновенно выдаётся результат сканированием индекса.
План такой:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost  |
---------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |     1 |    23 |     4 |
|   1 |  SORT AGGREGATE              |      |     1 |    23 |       |
|   2 |   FIRST ROW                  |      |     2 |    46 |     4 |
|*  3 |    INDEX RANGE SCAN (MIN/MAX)| LIM  |     2 |    46 |     4 |
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("ACC"='014654567 ' AND "CURRCODE"='000')
Note
-----
   - 'PLAN_TABLE' is old version
   - cpu costing is off (consider enabling it)



На втором сервере имеется такая же таблица-копия изменений остатков по счетам за последние 20 лет, но партиционированная по датам.
Один день - одна партиция, в среднем по 100000 строк в день:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table LIM
(
  PRODATE      DATE not null, -- дата остатка
  ACC          VARCHAR2(10) not null, -- номер счёта
  CURRCODE     VARCHAR2(3) not null, -- валюта счёта
  LIM          NUMBER -- остаток по счёту
)
partition by range (PRODATE)
(
  partition LIM_1997_04_29 values less than (TO_DATE(' 1997-04-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition LIM_1997_04_30 values less than (TO_DATE(' 1997-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  ...
  partition LIM_2016_10_06 values less than (TO_DATE(' 2016-10-07 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition LIM_2016_10_07 values less than (TO_DATE(' 2016-10-08 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
);



Есть локальный индекс для определения остатка по счёту на дату:

Код: plsql
1.
create unique index IX_L_LIM_ACC_CURR_UQ on LIM (ACC, CURRCODE, PRODATE) nologging  local;



Запрашиваем дату последнего изменения остатка по счёту:

Код: plsql
1.
select max(prodate) from lim where acc = '014654567 ' and currcode = '000';



Результат выдаётся только через 1 минуту, т.к. оракл сканирует все партиции и не может сообразить, что партиции надо сканировать в обратном порядке, начиная с последней, и где-то в самых последних партициях и будет вероятнее всего найдена последняя дата изменения остатка по счёту.
Когда где-то в самых последних партициях будет найдена последняя дата изменения остатка по счёту, тогда ораклу стоило бы прекращать дальнейшее сканирование локального индекса.
План такой:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
| Id  | Operation                     | Name                 | Rows  | Bytes | C
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                      |     1 |    23 | 1
|   1 |  SORT AGGREGATE               |                      |     1 |    23 |
|   2 |   PARTITION RANGE ALL         |                      |     1 |    23 | 1
|   3 |    FIRST ROW                  |                      |     1 |    23 | 1
|*  4 |     INDEX RANGE SCAN (MIN/MAX)| IX_L_LIM_ACC_CURR_UQ |     1 |    23 | 1
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("ACC"='014654567 ' AND "CURRCODE"='000')
Note
-----
   - 'PLAN_TABLE' is old version



Кстати, запрос минимальной даты на втором сервере тоже висит минуту, как и запрос максимальной даты:

Код: plsql
1.
select min(prodate) from lim where acc = '014654567 ' and currcode = '000';



Статистика на втором сервере собирается обычным dbms_stats.gather_table_stats по партициям со стандартными параметрами.

Итак, скан по локальному индексу партиционированной таблицы происходит на несколько порядков медленнее скана по индексу непарциционированной таблицы.
Вопрос, как на втором сервере научить оракл сообразить, что партиции надо сканировать в обратном порядке, начиная с последней, и где-то в самых последних партициях и будет вероятнее всего найдена последняя дата изменения остатка по счёту?
(И когда где-то в самых последних партициях будет найдена последняя дата изменения остатка по счёту, тогда ораклу стоило бы прекращать дальнейшее сканирование локального индекса.)
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322615
yon_brover,

а что ты хотел, если у тебя ключ секционирования не участвует в условия запроса? партишн прунинг не работает и приходится сканить каждую секцию индекса секционированной таблицы. и тут, как бы тебе не хотелось, но прочитать надцать маленьких индексов выходит медленнее, чем один большой, так как возникает оверхед по лишнему чтению структур индекса каждой его секции.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322621
yon_broverне может сообразить, что партиции надо сканировать в обратном порядке, начиная с последней, и где-то в самых последних партициях и будет вероятнее всего найдена последняя дата изменения остатка по счёту.это с какого перепугу и на каких таких "подсказках" от тебя в виде констрейнтов, схемы секционирования и т.д. оракл должен был понять такое? где и чем ты ему гарантируешь, что всё оно будет именно так, как ты сказал, а не как-то по другому? лично я бы тебе на слово не поверил. собственно, оракл поступил также.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322680
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
yon_broverНа втором сервере имеется такая же таблица-копия изменений остатков по счетам за последние 20 лет, но партиционированная по датам.
Один день - одна партиция
365*20=7300 секций, у Вас, видимо, какая-то особенная редакция oracle - обычный EE не позволяет больше 1000 создавать (3 года при посуточной нарезке).
По сути вопроса - поскольку старые данные не удаляете, то просто замените индекс на глобальный и будет счастье.
Из минусов - с очевидностью старые секции объединяются в более крупные, чтобы нарезать новые суточные секции.
Эта операция станет дороже за счет необходимости обновлять глобальный индекс.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322688
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эхэто с какого перепугу и на каких таких "подсказках" от тебя в виде констрейнтов, схемы секционирования и т.д. оракл должен был понять такое? где и чем ты ему гарантируешь, что всё оно будет именно так, как ты сказал, а не как-то по другому? лично я бы тебе на слово не поверил. собственно, оракл поступил также.
Ну не надо так категорично. Как раз в данном случае оптимизатор должен был разобраться, что нужно сканировать партиции с конца.
yon_brover...
Результат выдаётся только через 1 минуту, т.к. оракл сканирует все партиции и не может сообразить, что партиции надо сканировать в обратном порядке, начиная с последней, и где-то в самых последних партициях и будет вероятнее всего найдена последняя дата изменения остатка по счёту
...
Вы по своему плану не определите, все партиции сканировались или не все.
И в каком порядке.
Всегда в таком случае смотрите Pstart и Pstop и включите пошаговую статистику.

Так что приводите версию и полный план с пошаговой статистикой выполнения.
Или, если вам лень, просто делаете индекс глобальным, как показали выше.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322696
Maxim Demenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

Почему только 1000 ?

Best regards

Maxim
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322701
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

авторобычный EE не позволяет больше 1000 создавать
это где такое написано?
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322702
Maxim Demenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|Ну не надо так категорично. Как раз в данном случае оптимизатор должен был разобраться, что нужно сканировать партиции с конца.


Но подобная оптимизация была введена с 11.1.0.6, версия ТС пока не озвучена. И я не уверен что она работает в случае доступа по индеху.

Best regards

Maxim
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322703
д0k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousyon_broverНа втором сервере имеется такая же таблица-копия изменений остатков по счетам за последние 20 лет, но партиционированная по датам.
Один день - одна партиция
365*20=7300 секций, у Вас, видимо, какая-то особенная редакция oracle - обычный EE не позволяет больше 1000 создавать (3 года при посуточной нарезке).
По сути вопроса - поскольку старые данные не удаляете, то просто замените индекс на глобальный и будет счастье.
Из минусов - с очевидностью старые секции объединяются в более крупные, чтобы нарезать новые суточные секции.
Эта операция станет дороже за счет необходимости обновлять глобальный индекс.

А что я сделал не так ?

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
sqlplus / as sysdba 

SQL*Plus: Release 11.2.0.2.0 Production on Fri Oct 7 12:50:42 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select  table_name ,  count(*)  from  dba_tab_partitions  group by table_name    having count(*) >1000; 

TABLE_NAME                       COUNT(*)
------------------------------ ----------
XXX_COYYY                           4172
SYSAUD$                              1103
ZZZZ_KEEPER                          3278
WERT                                 5301
MMNBV                                2897
ASD_LOG                              4172

7 rows selected.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322708
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
K790авторобычный EE не позволяет больше 1000 создавать
это где такое написано?
Ну вообще в logical database limits, а что?
https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits003.htm
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322712
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
д0kА что я сделал не так ?
Эээ... забыли забыли включить в группировку владельца?
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322713
AlexFF__| Как раз в данном случае оптимизатор должен был разобраться, что нужно сканировать партиции с конца.
с куя ли при секционировании по prodate и при запросе вида:
select max(prodate) from lim where acc = '014654567 ' and currcode = '000' ;
сканирование должно идти с конца секций? в каком месте написано и гарантируется серверу, что строки со значением acc = '014654567 ' and currcode = '000' лежат именно в последней секции, а не в первой, или не где-то в середине, если секции нарезаны по prodate?
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322714
д0k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousK790пропущено...

это где такое написано?
Ну вообще в logical database limits, а что?
https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits003.htm

1024K - 1
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322715
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim DemenkoAlexFF__|Ну не надо так категорично. Как раз в данном случае оптимизатор должен был разобраться, что нужно сканировать партиции с конца.


Но подобная оптимизация была введена с 11.1.0.6, версия ТС пока не озвучена. И я не уверен что она работает в случае доступа по индеху.

Best regards

Maxim
Поэтому и спрашиваю версию.
А по индексу все-таки должно работать. Можно даже тест сделать. Потом )
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322716
Maxim Demenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

Так там 1024K - 1

Best regards

Maxim
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322719
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousK790пропущено...

это где такое написано?
Ну вообще в logical database limits, а что?
https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits003.htm

= 1 024 K, насколько я понимаю это к тысячам кило, т.е. миллион как минимум. -1 только не пойму, что это и почему именно -1 :)
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322721
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - ЭхAlexFF__| Как раз в данном случае оптимизатор должен был разобраться, что нужно сканировать партиции с конца.
с куя ли при секционировании по prodate и при запросе вида:
select max(prodate) from lim where acc = '014654567 ' and currcode = '000' ;
сканирование должно идти с конца секций? в каком месте написано и гарантируется серверу, что строки со значением acc = '014654567 ' and currcode = '000' лежат именно в последней секции, а не в первой, или не где-то в середине, если секции нарезаны по prodate?
Потому что сканируя с конца, можно остановиться, найдя первую запись =)
Неужели это в голову не приходит?
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322722
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
K790,

хотя есть подозрение, что за минусом первой партиции.
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322723
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
д0k1024K - 1
Шит. Бывает же. А мы как в анекдоте - до сих пор паровозы под откос пускаем...
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322724
д0k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
K790andrey_anonymousпропущено...

Ну вообще в logical database limits, а что?
https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits003.htm

= 1 024 K, насколько я понимаю это к тысячам кило, т.е. миллион как минимум. -1 только не пойму, что это и почему именно -1 :)

потому, что люди считают начиная с единицы , а компьютеры начиная с нуля...
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322728
д0k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousд0kА что я сделал не так ?
Эээ... забыли забыли включить в группировку владельца?

согласен

но всервно больше 1000
Код: plsql
1.
2.
3.
4.
5.
select  max (cnt ) from (select  table_owner,  table_name ,  count(*) cnt   from  dba_tab_partitions  group by table_name , table_owner    having count(*) >1000);

  MAX(CNT)
----------
      3297
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322730
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Быстренько, по структуре ТС:

Создаем таблицу с 99 дневными партициями + индекс
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table LIM
(
  PRODATE      DATE not null,
  ACC          VARCHAR2(10) not null,
  CURRCODE     VARCHAR2(3) not null,
  LIM          NUMBER
)
partition by range (PRODATE)
(
  partition P_1 values less than ( date '2016-01-02' ),
  ...
  partition P_99 values less than ( date '2016-04-09' )
);

create unique index IDX_LIM on LIM (ACC, CURRCODE, PRODATE) local;




Вставляем в каждую партицию по 10 записей так, чтобы в последней не было таких, что удовлетворяют условию запроса
Код: plsql
1.
2.
insert into LIM
  select date '2016-01-01' + rownum/10, case when date '2016-01-01' + rownum/10 < date '2016-04-08' then mod(rownum, 10) else 100 end, '000', rownum from dual connect by rownum < 990;



Код: plsql
1.
2.
select max(prodate) from T_TEST where acc = '5' and currcode = '000';
07.04.2016 12:00:00


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |            |      1 |        |       |     1 (100)|          |       |       |      1 |00:00:00.01 |       2 |
|   1 |  SORT AGGREGATE               |            |      1 |      1 |    19 |            |          |       |       |      1 |00:00:00.01 |       2 |
|   2 |   FIRST ROW                   |            |      1 |      1 |    19 |     1   (0)| 00:00:01 |       |       |      1 |00:00:00.01 |       2 |
|   3 |    PARTITION RANGE ALL        |            |      1 |      1 |    19 |     1   (0)| 00:00:01 |    99 |     1 |      1 |00:00:00.01 |       2 |
|*  4 |     INDEX RANGE SCAN (MIN/MAX)| IDX_LIM    |      2 |      1 |    19 |     1   (0)| 00:00:01 |    99 |     1 |      1 |00:00:00.01 |       2 |
------------------------------------------------------------------------------------------------------------------------------------------------------
 
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322739
Ханч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
yon_brover,

Покаж план этого запроса (и время выполнения):

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select
prodate
from
(
select /*+ index_rs_desc(lim IX_L_LIM_ACC_CURR_UQ) */ 
prodate 
from 
lim 
where 
acc = '014654567 ' and currcode = '000' 
order by prodate desc
) where rownum<=1
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322741
Maxim Demenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexFF__|,

да, у меня та же картина , походу работает.

Best regards

Maxim
...
Рейтинг: 0 / 0
Cкан партиционированной таблицы медленнее непарциционированной.
    #39322745
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Demenkoда, у меня та же картина , походу работает.
Но ТС рекомендация прежняя - создать глобальный (можно секционированный по hash от ACC) индекс.
...
Рейтинг: 0 / 0
25 сообщений из 47, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Cкан партиционированной таблицы медленнее непарциционированной.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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