0% found this document useful (0 votes)
40 views12 pages

Partitioning in Oracle 1728042170

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views12 pages

Partitioning in Oracle 1728042170

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

INDEX

 1.TYPES OF PARTITIONS
 A.TABLE_PARTITIONS
o 1)RANGE PARTITION
 i)range interval
 ii)reference interval
o 2)HASH PARTITION
o 3)COMPOSITE PARTITION
o 4)LIST PARTITION

 B.PARTITIONED INDEXES
o 1)GLOBAL INDEXES
o 2)LOCAL INDEXES

 C.PARTITION PRUNING
o 1)TYPES
o 2)CONDITIONS
o 3)EXAMPLE

 D.EXTRAS

 E.REFRENCE

1. TYPES OF PARTITIONS

A.TABLE PARTITIONS

1)RANGE PARTITION
Range partitioning is a convenient method for partitioning historical data. The boundaries of
range partitions define the ordering of the partitions in the tables or indexes.
Range partitioning is also ideal when you periodically load new data and purge old data, because
it is easy to add or drop partitions.

You should consider range or interval partitioning when:

 You often scan large tables using a date column like TRANSACION_DATE ,ORDER_DATE.
 You need to maintain a rolling window of data.
 You want to perform admin tasks like backup and restore more easily by dividing large tables
into smaller, manageable pieces based on date ranges.
i) Range Interval Partition
Interval partitioning is an extension to range partitioning in which, beyond a point in time,
partitions are defined by an interval. Interval partitions are automatically created by the database
when data is inserted into the partition.

ii) Reference Interval Partition


A reference partition is a partitioning technique used to maintain a relationship between two
tables based on their partitioning keys. Reference partitioning allows you to partition a child table
in the same way as a parent table, ensuring that data remains consistent and that queries can
efficiently join the two tables. It's particularly useful when you have a parent table (like orders)
and a child table (like order items), and you want to ensure that each order item is stored in the
same partition as its corresponding order.
You cannot use interval partitioning with reference partitioned tables.

CREATE TABLE TRANSACTIONS1


(TRANSACTION_ID NUMBER NOT NULL,
TRANSACTION_DATE DATE NOT NULL)
PARTITION BY RANGE (TRANSACTION_DATE)
(PARTITION PARTITION11 VALUES LESS THAN (TO_DATE('01/04/2023', 'DD/MM/YYYY')),
PARTITION PARTITION12 VALUES LESS THAN (TO_DATE('01/07/2023', 'DD/MM/YYYY')),
PARTITION PARTITION13 VALUES LESS THAN (TO_DATE('01/09/2023', 'DD/MM/YYYY')),
PARTITION PARTITION14 VALUES LESS THAN (TO_DATE('01/01/2024', 'DD/MM/YYYY')));

2) HASH PARTITION

Sometimes it's unclear where data should go, even if you know the partitioning key. Instead of
grouping similar data like in range partitioning, hash partitioning randomly distributes data across
partitions using a hashing algorithm. This method can work well for certain datasets, but it may not
be effective for managing historical data.

You should consider hash partitioning when:

 Your queries access data randomly, not in a sequence.


 You want to evenly distribute data to prevent I/O bottlenecks.
 You're managing very large tables and want to avoid oversized partitions.
 The data doesn’t fit into clear ranges or logical groups, making range partitioning difficult.

CREATE TABLE TRANSACTIONS2


(TRANSACTION_ID NUMBER NOT NULL,
TRANSACTION_DATE DATE NOT NULL)
PARTITION BY HASH (TRANSACTION_DATE)
(PARTITION p1 TABLESPACE users,
PARTITION p2 TABLESPACE users1,
PARTITION p3 TABLESPACE users2,
PARTITION p4 TABLESPACE users3);

In this definition of the table, I have "randomly" distributed incoming rows across 4 Partitions in 4
different Tablespaces. Given the incoming " transaction_date" values ,Each of the 4 Partitions would
be equally loaded.
3) Composite Partition

a) Range-Hash
b) Range-List
c) Range-Range
d) List-Range
e) List-Hash
f) List-List
g) Interval-Hash
h) Interval-List
i) Interval-Range

CREATE TABLE TRANSACTIONS3


(TRANSACTION_ID NUMBER NOT NULL,
TRANSACTION_DATE DATE NOT NULL)
PARTITION BY RANGE (TRANSACTION_DATE)
SUBPARTITION BY HASH (TRANSACTION_ID)
(PARTITION PARTITION1 VALUES LESS THAN (TO_DATE('01/04/2023', 'DD/MM/YYYY')),
PARTITION PARTITION2 VALUES LESS THAN (TO_DATE('01/07/2023', 'DD/MM/YYYY')),
PARTITION PARTITION3 VALUES LESS THAN (TO_DATE('01/09/2023', 'DD/MM/YYYY')),
PARTITION PARTITION4 VALUES LESS THAN (TO_DATE('01/01/2024', 'DD/MM/YYYY')));

4) LIST PARTITION

You should use list partitioning when you want to specifically map rows to partitions based on
discrete values.

Unlike range and hash partitioning, multi-column partition keys are not supported for list
partitioning. If a table is partitioned by list, the partitioning key can only consist of a single column of
the table.

CREATE TABLE accounts


( id NUMBER
, account_number NUMBER
, customer_id NUMBER
, branch_id NUMBER
, region VARCHAR(2)
, status VARCHAR2(1)
)
PARTITION BY LIST (region)
( PARTITION p_northwest VALUES ('OR', 'WA')
, PARTITION p_southwest VALUES ('AZ', 'UT', 'NM')
, PARTITION p_northeast VALUES ('NY', 'VM', 'NJ')
, PARTITION p_southeast VALUES ('FL', 'GA')
, PARTITION p_northcentral VALUES ('SD', 'WI')
, PARTITION p_southcentral VALUES ('OK', 'TX')
);

B.PARTITIONED INDEXES:-

1.GLOBAL INDEX

i)Global partitioned
An index that is partitioned independently of the underlying table partitions. This allows for more
flexible data management. There will be multiple segment for global partitioned index.We can
create multiple partitions as much as we want .It is independent of table partitions.

Means if table has 32 partitions then we can create no of index partitions as per our choice.

It is not necessary no of index partitions should be equal to no of table partitions in global


partition index.

Below we are trying to create global partition index but we got error because we have specified

Range for partition and it is not covering whole table hence me met with below error.

In this case we can do 2 things :-


i) We can create index without specifying range or

ii) Need to create one partition as maxvalue.

SQL> CREATE INDEX IDX_GLOBAL_PART2 ON TRANSACTIONS1(TRANSACTION_DATE)


GLOBAL PARTITION BY RANGE (TRANSACTION_DATE) (
PARTITION IDX1 VALUES LESS THAN (TO_DATE('01/04/2001', 'DD/MM/YYYY')),
PARTITION IDX2 VALUES LESS THAN (TO_DATE('01/07/2001', 'DD/MM/YYYY'))
); 2 3 4

ERROR at line 5:
ORA-14021: MAXVALUE must be specified for all columns

SQL> CREATE INDEX idx_global_part ON TRANSACTIONS1(TRANSACTION_DATE);

Index created.

SQL> CREATE INDEX IDX_GLOBAL_PART2 ON TRANSACTIONS1(TRANSACTION_DATE)


GLOBAL PARTITION BY RANGE (TRANSACTION_DATE) (
PARTITION IDX1 VALUES LESS THAN (TO_DATE('01/04/2001', 'DD/MM/YYYY')),
PARTITION IDX2 VALUES LESS THAN (TO_DATE('01/07/2001', 'DD/MM/YYYY')),
2 3 4 5 PARTITION IDX_REMAIN VALUES LESS THAN (MAXVALUE)
); 6

Index created.

Also if you try to create global partition index on column other than partition column you will end
with below error. GLOBAL non-prefixed partitioned index are not supported by oracle. If you want
to create a non-prefixed index, it must be created as LOCAL .

SQL> CREATE INDEX idx_global_part ON TRANSACTIONS1(TRANSACTION_ID)


GLOBAL PARTITION BY HASH (TRANSACTION_DATE); 2
GLOBAL PARTITION BY HASH (TRANSACTION_DATE)
*
ERROR at line 2:
ORA-14038: GLOBAL partitioned index must be prefixed

SQL> CREATE INDEX idx_global_part ON TRANSACTIONS1(TRANSACTION_DATE)


GLOBAL PARTITION BY HASH (TRANSACTION_ID); 2
GLOBAL PARTITION BY HASH (TRANSACTION_ID)
*
ERROR at line 2:
ORA-14038: GLOBAL partitioned index must be prefixed

ii)Global non partitioned

A standard index that is not partitioned and covers the entire table. There will be only one segment
for global non partitioned index.

SQL> CREATE INDEX idx_global_non_part ON TRANSACTIONS1 (TRANSACTION_DATE);

Index created.

Global Prefixed Indexes –

Global prefixed index is Creating index as per partition key column . A global prefixed index in
Oracle is a type of index that is global (not tied to specific partitions of a partitioned table) and is
defined with a leading column (or columns) that enhances query performance when filtering by that
column.

If you are creating global partition index on other column than partition key i.e Global Non-Prefixed
Indexes , you will get error ORA-14038: GLOBAL partitioned index must be prefixed .But you can
create non-partitioned global prefixed index.

SQL> CREATE INDEX idx_global_prefixed ON TRANSACTIONS1(TRANSACTION_ID,TRANSACTION_DATE);

Index created.

SQL> CREATE INDEX idx_global_non_prefix ON TRANSACTIONS1(TRANSACTION_DATE)


GLOBAL PARTITION BY HASH (TRANSACTION_id); 2
GLOBAL PARTITION BY HASH (TRANSACTION_id)
*
ERROR at line 2:
ORA-14038: GLOBAL partitioned index must be prefixed

SQL> CREATE INDEX idx_global_prefix ON TRANSACTIONS1(TRANSACTION_DATE);

Index created.

Global Non-Prefixed Indexes -


Creating index on another column than partition key column .Oracle does not support Global Non
Prefixed indexes.

2. LOCAL INDEX

local indexes are inherently tied to the partitioning of the table ,it must be partitioned according to
the table's partitioning scheme. If you want a non-partitioned index, you should create a global non-
partitioned index instead.

Local Prefixed Indexes - (local indexes on partition key column)

SQL> CREATE INDEX idx_local_prefixed ON TRANSACTIONS1(TRANSACTION_DATE) LOCAL;

Index created.

Local Non-Prefixed Indexes - (local indexes on other than partition key column)

SQL> CREATE INDEX idx_local_non_prefixed ON TRANSACTIONS1(TRANSACTION_ID) LOCAL;

Index created.

When to create global index and when to create local index ?

For example, suppose there is a primary key on TRANS, on the TRANS_ID column. The primary key
can be anywhere inside the table, across all the partitions. In this case, the index entries of a
partition of the table may exist outside the corresponding partition of the index. For such a situation,
create a global index.

i) local indexes are easier to manage and oracle automatically manages the maintainance.

ii) Global indexes are not managed by oracle automatically, Means if we drop any partitions from
table global index will go unusable.In this case you need to rebuild them or you can drop partition
with clause update global indexes.
alter table table_name drop partition part1 update global indexes;

C.PARTITION PRUNING

Partition pruning ensure that queries can skip irrelevant partitions by filtering on partition keys. This
reduces the amount of data scanned.

There are two types of partition pruning:(TYPES)

o Static partition pruning: If the where condition has constant values. (Compile time)
o Dynamic partition pruning: If the where condition has some calculations, functions, etc.
(Run time)

To optimize queries with range partitions, use your partition key with these conditions:

CONDITIONS:-

 Range Conditions: Use =, <, <=, >, >=, BETWEEN, or LIKE to compare the key with
literals or bind variables.
o Examples:
 col = :my_date
 col BETWEEN :my_date AND :my_date + 3
 col = (SELECT processing_date FROM
current_processing_date)

For list and hash partitions, use = or IN predicates.

 Using functions on partition columns prevents partition pruning. This includes any
type conversions.
For example
WHERE TRUNC(my_column) BETWEEN SYSDATE - 30 AND SYSDATE

EXAMPLE:-

i) We have created a range partition table called TRANSACTIONS1.

And inserted 4 records 1 record in each partition. After commiting performed stats gather.

SQL> CREATE TABLE TRANSACTIONS1


(TRANSACTION_ID NUMBER NOT NULL,
TRANSACTION_DATE DATE NOT NULL)
PARTITION BY RANGE (TRANSACTION_DATE)
(PARTITION PARTITION11 VALUES LESS THAN (TO_DATE('01/04/2023', 'DD/MM/YYYY')),
PARTITION PARTITION12 VALUES LESS THAN (TO_DATE('01/07/2023', 'DD/MM/YYYY')),
PARTITION PARTITION13 VALUES LESS THAN (TO_DATE('01/09/2023', 'DD/MM/YYYY')),
PARTITION PARTITION14 VALUES LESS THAN (TO_DATE('01/01/2024', 'DD/MM/YYYY'))); 2 3 4
5 6 7 8

Table created.

SQL>
SQL> insert into TRANSACTIONS1 values(1,'01-MAR-2023');
insert into TRANSACTIONS1 values(2,'01-JUN-2023');
insert into TRANSACTIONS1 values(3,'01-JUL-2023');
insert into TRANSACTIONS1 values(4,'01-DEC-2023');
1 row created.

SQL>
1 row created.

SQL>
1 row created.

SQL>

1 row created.

SQL> execute dbms_stats.gather_table_stats(ownname => 'NITESH', tabname =>'TRANSACTIONS1');


PL/SQL procedure successfully completed.

SQL> col table_name for a30


col partition_name for a30SQL>
SQL>
SQL> SELECT table_name,

num_rows
FROM user_tab_partitions
WHERE table_name like 'TRANSACTIONS1%'
ORDER BY table_name, partition_name; 2 3 4 5 6

TABLE_NAME PARTITION_NAME NUM_ROWS

ii)Now we run a simple select statement and check for execution plan.Focus on the Pstart and Pstop
columns in the execution plan. Without a filter, all partitions are read. (partition range all)

If we add a WHERE condition using the partition key, the execution plan will change to read only the
relevant partitions. In some case If you see "KEY" in the Pstart and Pstop columns, it means the
query parser couldn't identify which partitions to access, but the optimizer expects partition pruning
to happen during execution. This often occurs when there’s an equality condition on the partition
key that involves a function.
Iii)Here Using functions in the WHERE clause cancels partition pruning, causing the database to read
all partitions. if TRANSACTION_DATE is already a date type, converting it to a date again might lead
to performance issues because it forces a conversion for every row and cancels partition pruning .
Hence you should avoid using functions on colums.You can use the functions on literals.

Below query directly compares the TRANSACTION_DATE column without any function applied.

This is more efficient, especially if TRANSACTION_DATE is already in a date format. It allows for
better performance and can leverage partition pruning if applicable.
EXTRAS:-

1.OUTPUT RATIO:-

Consider you have table with 10M rows that has been partitioned into four partitions then,

i) If your query is fetching less than or equal to 10 to 15 % rows ,then it should go for index scan if
there is filter condition as per indexed column.

ii) If your query is fetching more than 15 to 70 % rows ,then it should go for partition pruning.

iii) If your query is fetching more than 70% rows then it should be full table scan.(check for
db_file_multiblock_read parameter).

2. How to decide on which column we should create partition.

Cardinality: Prefer columns with a high cardinality (many distinct values) to ensure even distribution
of data across partitions.

Skewed Data: Avoid columns with skewed distributions that might lead to uneven partition sizes,
which can affect performance.

Historical Data Management: Use columns that reflect the data's lifecycle, such as dates (e.g.,
order_date), which can help with archiving and purging old data.

Time-Based Queries: If data is often queried based on time periods (e.g., monthly or yearly),
consider date columns for range partitioning.

3. VIEWS

 DBA_PART_TABLES
 DBA_TAB_PARTITIONS
 DBA_TAB_SUBPARTITIONS
 DBA_PART_KEY_COLUMNS
 DBA_SUBPART_KEY_COLUMNS
 DBA_PART_COL_STATISTICS
 DBA_SUBPART_COL_STATISTICS
 DBA_PART_HISTOGRAMS
 DBA_SUBPART_HISTOGRAMS

 DBA_PART_INDEXES
 DBA_IND_PARTITIONS
 DBA_IND_SUBPARTITIONS

4. INTERVAL IN PARTITION
1) NUMTOYMINTERVAL

Purpose: Converts a number into an interval Year to Month(NUMTOYMINTERVAL).

Use: Helpful for creating partitions based on years or months.

2) NUMTODSINTERVAL

Purpose: Converts a number into an interval Day to Second(NUMTODSINTERVAL).

Use: Useful for creating partitions based on days or smaller time intervals.

5. Why row movement should be enabled for partition table?

If row movement is not enabled, changes that would require a row to be moved to another partition
might result in errors. Please check below example for ref(table is range partition).

i) Modifying partitioning strategies, such as splitting or merging partitions, can also affect ROWIDs as
rows may need to be relocated.
ii) Also if we are changing partition key .

iii) If you perform update column(partitioned key column) that requires a row to be moved , you
need to enable row movement else you will end with below error.

SQL> select owner,table_name,row_movement from dba_tables where table_name='TRANSACTIONS1';


OWNER TABLE_NAME ROW_MOVE

NITESH TRANSACTIONS1 DISABLED

SQL> update NITESH.TRANSACTIONS1 set TRANSACTION_DATE='01-DEC-2023' where transaction_id=8;


update NITESH.TRANSACTIONS1 set TRANSACTION_DATE='01-DEC-2023' where transaction_id=8
*
ERROR at line 1:
ORA-14402: updating partition key column would cause a partition change

SQL> alter table TRANSACTIONS1 enable row movement;

Table altered.

SQL> update NITESH.TRANSACTIONS1 set TRANSACTION_DATE='01-DEC-2023' where transaction_id=8;

1 row updated.
SQL>

REFERENCES;

1. Oracle Documentation
2. Hemant Oracle DBA Blog
3. OraFAQ Partition Pruning

You might also like