Professional Documents
Culture Documents
Gavin Soorma,
Senior Oracle DBA, Bankwest
Agenda
• Each partition has its own name, and may optionally have its own storage
characteristics.
Partition Partition
Partition Partition
Partition Partition
Partition Partition
Who Partitions?
• For 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.
Decisions and Challenges
• License cost of Partitioning option (~11,000$ per CPU)
• Number of Partitions.
• All partitions, except the first, have an implicit lower bound specified
by the VALUES LESS THAN clause on the previous partition
• List Partitioning is useful for data that has discrete or distinct values.
• Pre 11g new partitions must be created in advance for new data.
PARTITION_NAME
------------------------------
P_FIRST
SQL> insert into order_details
values
(10001,'15-JAN-2009');
1 row created.
SQL> commit;
Commit complete.
PARTITION_NAME
------------------------------
P_FIRST
SYS_P101
REF Partitioning
• Related tables benefit from the same partitioning strategy.
Example:Orders and Line Items table
Child table inherits the same partitioning strategy as the parent table
via PK-FK relationships.
FOREIGN KEY
(order_id)
FOREIGN KEY
(order_id)
SQL> ALTER TABLE mycustomers ADD CONSTRAINT p_cust_id PRIMARY KEY (cust_id);
Table altered.
CREATE TABLE mysales
(cust_id NUMBER NOT NULL, quantity_sold NUMBER(10,2),
amount_sold NUMBER(10,2),
CONSTRAINT fk_sales_01
FOREIGN KEY (cust_id)
REFERENCES mycustomers(cust_id))
PARTITION BY REFERENCE (fk_sales_01);
9i extended to Range/List
Range 11g 9i 8i
Jan 08 …
Feb 08 …
… … …
…
Dec 08 …
… … …
…
Jan 08 Feb 08 Mar 08 Dec 08
Order_date
11g Virtual Column Partitioning
Virtual column based Defined by one of the Orders table has a virtual
Partitioning abovementioned column that derives the sales
partition techniques region based on the first
and the partitioning key is three digits of the customer
based on a virtual column. account number. The orders
Virtual columns are not stored table is then list partitioned
on disk and only exist as by sales region.
metadata.
Partition Data Dictionary Views
• 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
Working with Partitions
Index partition
equipartitioned
with table
GLOBAL INDEX
PARTITION_NAME
---------------
P_FIRST
SYS_P81
SYS_P82
Index created.
PARTITION_NAME TABLESPACE_NAME
--------------- ------------------------------
P_FIRST EXAMPLE
SYS_P102 EXAMPLE
SYS_P103 EXAMPLE
Global Partitioned Index
• Can enable partition pruning to take place at the index level even if
not possible on the underlying partitioned table
CREATE INDEX order_id_ind_global
ON order_details (order_id)
Table Partitioned
GLOBAL PARTITION BY RANGE (order_id) on order_date
(PARTITION p_ind1 values less than (100001),
PARTITION p_ind2 values less than (200001),
PARTITION p_ind3 values less than (300001)); PARTITION p_ind3
values less than (300001))
*
ERROR at line 6:
ORA-14021: MAXVALUE must be specified for all columns
PARTITION_NAME
------------------------------
LOCAL Index
SALES_1998
SALES_1999
SALES_2000
SALES_2001
P_2009
Table altered.
PARTITION_NAME STATUS
------------------------------ --------
SALES_1998 USABLE
SALES_1999 UNUSABLE
SALES_2000 USABLE
SALES_2001 USABLE
P_2009 USABLE
SQL> ALTER TABLE sales_data TRUNCATE PARTITION sales_1999_h2;
Table truncated.
PARTITION_NAME STATUS
------------------------------ --------
P1 UNUSABLE
P2 UNUSABLE
P_OTHERS UNUSABLE
System altered.
COUNT(*)
----------
310
SQL> EXPLAIN PLAN FOR SELECT COUNT(*) FROM sales_data
WHERE time_id ='01-DEC-1999';
Explained.
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 |
------------------------------------------------------------------------------------------------------
Index altered.
SQL> EXPLAIN PLAN FOR SELECT COUNT(*) FROM sales_data WHERE time_id
='01-DEC-1999';
Explained.
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 |
----------------------------------------------------------------------------------------------------------
Update Global Indexes
• By default, many table maintenance operations on partitioned tables
invalidate (mark UNUSABLE) global indexes.
• Partition DDL statement takes longer to execute since indexes which were
previously marked UNUSABLE are updated
• Range Partitioning
– range, equality and IN-list predicates
• Hash Partitioning
– equality and IN-list predicates
SQL> EXPLAIN PLAN FOR SELECT COUNT(*) FROM sales_data WHERE
time_id='21-JAN-2000';
Explained.
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.
• Applies to Merge and Hash joins and not to Nested Loop joins.
Explained.
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)
0 sorts (disk) Note the physical reads and 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');
PARTITION_NAME
------------------------------
SALES_1998
SALES_1999
SALES_2000
SALES_2001
P_2009
COUNT(*)
----------
247945
PARTITION_NAME
------------------------------
SALES_1998
SALES_1999
SALES_2000
COUNT(*)
----------
259418
Table altered.
SQL> select partition_name from user_tab_partitions where
table_name='SALES_NO_PART';
PARTITION_NAME
------------------------------
SALES_1998
SALES_1999
SALES_2000
SALES_2001
Table altered.
COUNT(*)
----------
259418
THANKS FOR ATTENDING!
Gavin Soorma
gavin.soorma@bankwest.com.au