Professional Documents
Culture Documents
Partitioning - Let's Divide and Conquer!: Gavin Soorma, Senior Oracle DBA, Bankwest
Partitioning - Let's Divide and Conquer!: Gavin Soorma, Senior Oracle DBA, Bankwest
Agenda
What is Partitioning?
a) A Structure dividing a space into parts (noun)
b) To divide or separate (verb)
Source: Oxford English Dictionary
Each partition has its own name, and may optionally have its own storage
characteristics.
Really Big
Table
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Partition
Who Partitions?
Deciding on what and how to partition is both a Developer and
DBA job.
A good of understanding of the business rules needs to be
known about how the data is utilized within Oracle. For example,
how data is loaded and queried by the application?
A great portion of care needs to done in selection of the type of
partitioning along with the partition key.
Poor selection of partition or partition key could lead to poor DML
and DDL performance.
Always test, test, and test again prior to implementing in production.
Why Partition?
For Manageability
Partitioning enables data management operations such data loads, index
creation and rebuilding, and backup/recovery at the partition level, rather
than on the entire table. This results in significantly reduced times for these
operations.
For Performance
Partitioning improves query performance. In many cases, the results of a
query can be achieved by accessing a subset of partitions, rather than the
entire table. Partition Pruning and Partition-wise joins can provide orderof-magnitude gains in performance.
For Availability
Partitioning increases the availability of mission-critical databases if critical
tables and indexes are divided into partitions to reduce the maintenance
windows, recovery times, and impact of failures.
Oracle Partitioning
10 years of innovation
Database Release
Core Functionality
Range Partitioning
Oracle 8i
Oracle 9i
List Partitioning
Oracle 9i Release 2
Composite Range-List
Partitioning
Oracle 10g
Oracle 11g
Partitioning Methods
Oracle provides the following partitioning methods(pre 11g):
Range Partitioning
List Partitioning
Hash Partitioning
Composite Partitioning
Composite Partitioning
Range-Hash
Range-List
Partitioned by date_of_sale
then .
Partitioned by salesman_id
Partitioned by date_of_sale
then .
Partitioned by sales_region
RANGE Partitioning
Introduced in Oracle 8.0
Useful when Data has logical ranges into which it can be
distributed by example, a range of dates
Data is mapped to partitions based on ranges of partition key values
established for each partition
Each partition has a VALUES LESS THAN clause, which specifies a
non inclusive upper bound for the partitions.
All partitions, except the first, have an implicit lower bound specified
by the VALUES LESS THAN clause on the previous partition
A MAXVALUE literal can be defined for the highest partition.
MAXVALUE represents a virtual infinite value
Range Partitioning
Partitioning Method
create table order_details
(order_id number,
Partitioning Column (Key)
order_date date)
partition by range (order_date)
(partition p_jan values less than (to_date('01-FEB-2009','DD-MONYYYY')),
partition p_feb values less than (to_date('01-MAR-2009','DD-MONYYYY')),
partition p_mar values less than (to_date('01-APR-2009','DD-MONYYYY')),
partition p_2009 values less than (MAXVALUE)
)
;
Hash Partitioning
Introduced in Oracle 8i.
Enables partitioning of data that does not lend itself to
either range or list partitioning
As a better alternative to range partitioning when:
We do not know beforehand how much data maps to a
particular range.
The size of range partitions would differ substantially.
Range partitioning would cause the data to be undesirably
clustered.
Hash Partitioning
Hash Partitioning
List Partitioning
List Partitioning is useful for data that has discrete or distinct values.
SQL>
SQL>
1 row created.
SQL> commit;
Commit complete.
SQL> select partition_name from user_tab_partitions
where table_name='ORDER_DETAILS';
PARTITION_NAME
-----------------------------P_FIRST
SYS_P101
REF Partitioning
Related tables benefit from the same partitioning strategy.
Example:Orders and Line Items table
Redundant storage of the same data solves the problem.
But Data and maintenance overhead
Oracle 11g introduces REF partitioning
Child table inherits the same partitioning strategy as the parent table
via PK-FK relationships.
Enhanced performance as well as manageability.
Partition maintenance operations on parent table cascade to child
table.
RANGE
(order_date)
PRIMARY KEY
(order_id)
Jan 2009
Feb 2009
Dec 2009
Redundant storage of order_date
Table LINEITEMS
RANGE
(order_date)
FOREIGN KEY
(order_id)
Jan 2009
Feb 2009
Dec 2009
RANGE
(order_date)
PRIMARY KEY
(order_id)
Jan 2009
Feb 2009
Partition By Reference
Partitioning Key in Child Table
Inherited through PK-FK
relationship
Table LINEITEMS
RANGE
(order_date)
FOREIGN KEY
(order_id)
Jan 2009
Feb 2009
SQL>
SELECT TABLE_NAME, PARTITIONING_TYPE,
REF_PTN_CONSTRAINT_NAME FROM USER_PART_TABLES WHERE
TABLE_NAME IN ('MYCUSTOMERS','MYSALES');
TABLE_NAME
-----------------------------MYCUSTOMERS
MYSALES
PARTITION REF_PTN_CONSTRAINT_NAME
--------- -------------------------LIST
REFERENCE FK_SALES_01
List
Hash
Range
11g
9i
8i
List
11g
11g
11g
Range/Range
List/Range
List/List
Range-Range Partitioning
Ship_date
Jan 08
Feb 08
Dec 08
Jan 08
Feb 08
Order_date
Mar 08
Dec 08
ENAME
SAL YEARLY_SAL
-------------------- ---------- ---------SMITH
800
9600
ALLEN
1600
19200
WARD
1250
15000
MARTIN
1250
15000
TURNER
1500
18000
ADAMS
1100
13200
SQL> SELECT ename,sal,yearly_sal FROM emp_year_sal PARTITION(mid_sal);
ENAME
SAL YEARLY_SAL
-------------------- ---------- ---------JONES
2975
35700
BLAKE
2850
34200
CLARK
2450
29400
SCOTT
3000
36000
FORD
3000
36000
Sample Business
Usage
Range Partitioning
List Partitioning
Hash Partitioning
Composite Partitioning
Range-Range
Range-List
Range-Hash
List-List
List-Range
List-Hash
Based on a combination of
two of the above-mentioned
basic
techniques of Range, List,
Hash, and Interval
Partitioning
Partitioning Key
Interval Partitioning
Interval
Interval-Range
Interval-List
Interval-Hash
An extension to Range
Partition. Defined by an
interval, providing equi-width
ranges. With the exception of
the first partition all partitions
are automatically created
ondemand
when matching data
arrives.
REF Partitioning
DBA_PART_TABLES
DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS
DBA_PART_KEY_COLUMNS
DBA_PART_HISTOGRAMS
DBA_PART_INDEXES
DBA_IND_PARTITIONS
DBA_IND_SUBPARTITIONS
SQL>
create index order_det_ind_local on order_details
(order_date)
LOCAL
tablespace example;
Index created.
SQL>
select partition_name,tablespace_name from
user_ind_partitions where index_name='ORDER_DET_IND_LOCAL';
PARTITION_NAME
--------------P_FIRST
SYS_P102
SYS_P103
TABLESPACE_NAME
-----------------------------EXAMPLE
EXAMPLE
EXAMPLE
Can enable partition pruning to take place at the index level even if
not possible on the underlying partitioned table
Partition Maintenance
Operations
Add
Coalesce
Drop
Truncate
Split
Exchange
Move
Rename
Merge
.
Consider the effect of these operations on Index partitions ..
Partition Maintenance
ALTER TABLE sales ADD PARTITION jan96 VALUES LESS THAN ( '01-FEB1999' ) TABLESPACE tsx;
ALTER TABLE scubagear ADD PARTITION p_named TABLESPACE gear5;
ALTER TABLE parts MOVE PARTITION depot2 TABLESPACE ts094
NOLOGGING COMPRESS;
ALTER TABLE order_details
SPLIT PARTITION p_2009 AT (TO_DATE ('01-JUL-2009','DD-MON-YYYY'))
INTO (PARTITION p_2009h1, PARTITION p_2009h2);
ALTER TABLE four_seasons MERGE PARTITIONS quarter_one,
quarter_two INTO PARTITION quarter_two ;
Index Maintenance
LOCAL Index
STATUS
-------USABLE
UNUSABLE
USABLE
USABLE
USABLE
STATUS
-------UNUSABLE
UNUSABLE
UNUSABLE
SET SKIP_UNUSABLE_INDEXES=TRUE;
System altered.
SQL> SELECT COUNT (*) FROM sales_data
WHERE time_id ='01-DEC-1999
COUNT(*)
---------310
TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------Plan hash value: 1021418022
-----------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
-----------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
9 |
342 (26)| 00:00:05 |
|
|
|
1 | SORT AGGREGATE
|
|
1 |
9 |
|
|
|
|
|
2 |
PARTITION RANGE SINGLE|
|
276 | 2484 |
342 (26)| 00:00:05 |
2 |
2 |
|* 3 |
TABLE ACCESS FULL
| SALES_DATA |
276 | 2484 |
342 (26)| 00:00:05 |
2 |
2 |
------------------------------------------------------------------------------------------------------
sales_data
WHERE time_id
Explained.
SQL> SELECT * FROM
TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------Plan hash value: 3608419564
---------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
---------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
9 |
5
(0)| 00:00:01 |
|
|
|
1 | SORT AGGREGATE
|
|
1 |
9 |
|
|
|
|
|
2 |
PARTITION RANGE SINGLE|
|
310 | 2790 |
5
(0)| 00:00:01 |
2 |
2 |
|* 3 |
INDEX RANGE SCAN
| SALES_DATA_IND |
310 | 2790 |
5
(0)| 00:00:01 |
2 |
2 |
----------------------------------------------------------------------------------------------------------
Partition DDL statement takes longer to execute since indexes which were
previously marked UNUSABLE are updated
Partition Pruning
Very important feature for VLDB and Data Warehouses.
CBO eliminates unneeded partitions when building a partition access list.
Operations performed only on partitions relevant to the SQL statement
dramatically reduce the amount of disk reads as well as CPU time.
If using global partitioned indexes, can perform partition pruning on the index
partitions by eliminating index partitions even if table partitions cannot be
eliminated
Range Partitioning
range, equality and IN-list predicates
Hash Partitioning
equality and IN-list predicates
sales_data WHERE
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------Plan hash value: 1021418022
-----------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
-----------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
8 |
246
(3)| 00:00:03 |
|
|
|
1 | SORT AGGREGATE
|
|
1 |
8 |
|
|
|
|
|
2 |
PARTITION RANGE SINGLE|
|
468 | 3744 |
246
(3)| 00:00:03 |
5 |
5 |
|* 3 |
TABLE ACCESS FULL
| SALES_DATA |
468 | 3744 |
246
(3)| 00:00:03 |
5 |
5 |
------------------------------------------------------------------------------------------------------
The Pstart and Pstop columns indicate that a single partition has been accessed
by the optimizer even though the TABLE ACCESS FULL operation is indicated
Partition-wise Joins
Significantly improve the performance when joining tables with
millions of rows.
Useful in VLDB and DSS environments.
Applies to Merge and Hash joins and not to Nested Loop joins.
Two tables that are equi-partitioned on the join column.
Optimizer breaks the join operation into a number of smaller joins
that can be performed sequentially or in parallel.
If using parallel joins, will minimise the data exchanged by parallel
slaves
NOLOGGING
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------Plan hash value: 4232629991
-------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
-------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
839K|
44M| 1158 (10)| 00:00:14 |
|
|
|
1 | HASH GROUP BY
|
|
839K|
44M| 1158 (10)| 00:00:14 |
|
|
|
2 |
PARTITION HASH ALL |
|
839K|
44M| 1085
(4)| 00:00:14 |
1 |
4 |
|* 3 |
HASH JOIN
|
|
839K|
44M| 1085
(4)| 00:00:14 |
|
|
|
4 |
TABLE ACCESS FULL| CUSTOMERS_HASH | 62069 | 1818K|
61
(2)| 00:00:01 |
1 |
4 |
|
5 |
TABLE ACCESS FULL| SALES_DATA_HASH |
839K|
20M| 1012
(3)| 00:00:13 |
1 |
4 |
Statistics
---------------------------------------------------------7 recursive calls
0 db block gets
4794 consistent gets
296 physical reads
0 redo size
18197 bytes sent via SQL*Net to client
932 bytes received via SQL*Net from client
42 SQL*Net roundtrips to/from client
2 sorts (memory)
Note the physical reads and
0 sorts (disk)
consistent
gets using the Partition wise join on Hash
Partitioned versus Non Partitioned tables
Statistics
-------------------------------------------7 recursive calls
0 db block gets
6039 consistent gets
4100 physical reads
0 redo size
18197 bytes sent via SQL*Net to client
932 bytes received via SQL*Net from client
42 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
608 rows processed
Using DBMS_REDEFINITION
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('SH','SALES_NO_PART');
PL/SQL PROCEDURE SUCCESSFULLY COMPLETED.
CREATE TABLE "SH"."SALES_INTERIM"
(
"PROD_ID" NUMBER NOT NULL ENABLE,
...
) PCTFREE 5 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS
TABLESPACE "EXAMPLE"
PARTITION BY RANGE ("TIME_ID")
(PARTITION SALES_1998 VALUES LESS THAN (TO_DATE('01-JAN-1999','DD-MONYYYY')),
...
...
PARTITION SALES_2001 VALUES LESS THAN (TO_DATE('01-JAN-2002','DD-MONYYYY')),
PARTITION P_2009 VALUES LESS THAN (MAXVALUE)
);
DECLARE
ERROR_COUNT PLS_INTEGER := 0;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('SH', 'SALES_NO_PART',
'SALES_INTERIM',1, TRUE, TRUE, TRUE, FALSE,ERROR_COUNT);
DBMS_OUTPUT.PUT_LINE('ERRORS := ' || TO_CHAR(ERROR_COUNT));
END;
/
SQL> EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE
('SH','SALES_NO_PART','SALES_INTERIM');
PL/SQL PROCEDURE SUCCESSFULLY COMPLETED.
Exchange Partition
SQL> select partition_name from user_tab_partitions where
table_name='SALES_NO_PART';
PARTITION_NAME
-----------------------------SALES_1998
SALES_1999
SALES_2000
SQL> select count(*) from sales_2001; << NON PARTITIONED TABLE
COUNT(*)
---------259418
SQL> alter table sales_no_part add partition sales_2001
2 values less than ('01-JAN-2002') tablespace example;
Table altered.
SQL>
ALTER TABLE sales_no_part
EXCHANGE PARTITION sales_2001
WITH TABLE sales_2001
UPDATE GLOBAL INDEXES;
Table altered.
SQL> select count(*) from sales_no_part partition(sales_2001);
COUNT(*)
---------259418