Вы можете разбить на два столбца двумя способами:
- Многораздельное разбиение
- Составное разбиение (один столбец разделения, один столбец подраздела)
Многостолбцовое разбиение
При этом используется первый столбец, чтобы выбрать, в какой раздел помещать строку. Второй столбец оценивается только при значении ie. Это может привести к тому, что строки в разделе, которого вы не ожидали:
create table t (
c1 int, c2 int, c3 int
) partition by range ( c1, c2 ) (
partition p0 values less than ( 1, 1 ),
partition p1 values less than ( 2, 2 ),
partition p2 values less than ( 3, 3 )
);
insert into t values ( 0, 0, 1 );
insert into t values ( 0, 99, 2 );
insert into t values ( 1, 1, 3 );
select * from t partition ( p0 );
C1 C2 C3
0 0 1
0 99 2
Фильтрация по второму столбцу в списке приведет к минимальному сокращению раздела:
alter session set statistics_level = all;
set serveroutput off
select * from t
where c2 = 0;
select *
from table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST +PARTITION'));
----------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Pstart| Pstop | A-Rows |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | | 1 |
| 1 | PARTITION RANGE MULTI-COLUMN| | 1 | 1 |KEY(MC)|KEY(MC)| 1 |
|* 2 | TABLE ACCESS FULL | T | 3 | 1 |KEY(MC)|KEY(MC)| 1 |
----------------------------------------------------------------------------------------
(обратите внимание на Starts = 3
для TABLE ACCESS FULL
; это означает, что он читает все разделы)
Составное разбиение
Это «двухуровневое» разбиение. База данных сначала разбивает строки в разделе верхнего уровня. Затем далее подразделяется на второй уровень.
Ключевое различие между этим и несколькими столбцами в том, что вы можете иметь разные методы разбиения для каждого. например, range-ha sh, ha sh -list, et c.
create table t (
c1 int, c2 int, c3 int
) partition by range ( c1 )
subpartition by range ( c2 )
subpartition template (
subpartition s0 values less than ( 1 ),
subpartition s100 values less than ( 101 )
) (
partition p0 values less than ( 1 ),
partition p1 values less than ( 2 ),
partition p2 values less than ( 3 )
);
insert into t values ( 0, 0, 1 );
insert into t values ( 0, 99, 2 );
insert into t values ( 1, 1, 3 );
select * from t partition ( p0 );
C1 C2 C3
0 0 1
0 99 2
select * from t subpartition ( p0_s0 );
C1 C2 C3
0 0 1
Опять же, фильтрация столбца подразделения делает минимальное сокращение раздела. База данных сначала просканирует все разделы верхнего уровня. Затем только сокращайте подразделы в этих:
select * from t
where c2 = 0;
select *
from table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST +PARTITION'));
-----------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Pstart| Pstop | A-Rows |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | | 1 |
| 1 | PARTITION RANGE ALL | | 1 | 1 | 1 | 3 | 1 |
| 2 | PARTITION RANGE SINGLE| | 3 | 1 | 1 | 1 | 1 |
|* 3 | TABLE ACCESS FULL | T | 3 | 1 | | | 1 |
-----------------------------------------------------------------------------------
Обратите внимание на операцию PARTITION RANGE SINGLE
- это означает, что база данных получила доступ только к одному из подразделов.
В зависимости от схемы разбиения и распределения значений это может привести к значительному сокращению числа прочитанных строк. Вам нужно будет попробовать различные методы и границы раздела, чтобы понять, поможет ли это вам.