Académique Documents
Professionnel Documents
Culture Documents
Large
Data
Partitioning
Partitioning Overview
Indexing
Managing statistics
Compression
Purging
Backing up
Partitioning
Facts
Partitioning
Performance
Manageability
Oracle8
Range partitioning
Global range indexes
Static partition
pruning
Basic maintenance
operations: add,
drop, exchange
Oracle8i
Partition-wise joins
Dynamic pruning
Merge operation
Oracle9i
List partitioning
Oracle9i R2
Composite range-list
partitioning
Oracle10g
Oracle10g R2
Oracle
Database 11g
Global index
maintenance
Fast partition split
Local Index
maintenance
Multi-dimensional
pruning
Partitioning
Facts
Partitioning
Availability
Fast=True
Administration
Performance
Partitioning
Facts
part1.sql
Part1.sql
ops$tkyte%ORA11GR2> CREATE TABLE emp
2 ( empno
int,
3
ename
varchar2(20)
4 )
5 PARTITION BY HASH (empno)
6 ( partition part_1 tablespace p1,
7
partition part_2 tablespace p2
8 )
9 /
Table created.
ops$tkyte%ORA11GR2> insert into emp select empno, ename from scott.emp
2 /
14 rows created.
Part1.sql
ops$tkyte%ORA11GR2> select part1, part2
2
from (
3 select empno || ', ' || ename part1, row_number() over (order by empno) rn1
4
from emp partition(part_1)
5
) A FULL OUTER JOIN (
6 select empno || ', ' || ename part2, row_number() over (order by empno) rn2
7
from emp partition(part_2)
8
) B on ( a.rn1 = b.rn2 )
9 /
PART1
--------------7369, SMITH
7499, ALLEN
7654, MARTIN
7698, BLAKE
7782, CLARK
7839, KING
7876, ADAMS
7934, MILLER
PART2
--------------7521, WARD
7566, JONES
7788, SCOTT
7844, TURNER
7900, JAMES
7902, FORD
8 rows selected.
Part1.sql
ops$tkyte%ORA11GR2> alter tablespace p1 offline;
Tablespace altered.
ops$tkyte%ORA11GR2> select * from emp;
select * from emp
*
ERROR at line 1:
ORA-00376: file 3 cannot be read at this time
ORA-01110: data file 3:
'/home/ora11gr2/app/ora11gr2/oradata/ora11gr2/ORA11GR2/datafile/o1_mf_p1_6rprfr
mo_.dbf'
Part1.sql
ops$tkyte%ORA11GR2> variable n number
ops$tkyte%ORA11GR2> exec :n := 7844;
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2> select * from emp where empno = :n;
EMPNO ENAME
---------- -------------------7844 TURNER
Partitioning
Facts
Partitioning
SQL> create table big_table1
2 ( ID, OWNER, OBJECT_NAME, SUBOBJECT_NAME,
3
OBJECT_ID, DATA_OBJECT_ID,
4
OBJECT_TYPE, CREATED, LAST_DDL_TIME,
5
TIMESTAMP, STATUS, TEMPORARY,
6
GENERATED, SECONDARY )
7 tablespace big1
8 as
9 select ID, OWNER, OBJECT_NAME, SUBOBJECT_NAME,
10
OBJECT_ID, DATA_OBJECT_ID,
11
OBJECT_TYPE, CREATED, LAST_DDL_TIME,
12
TIMESTAMP, STATUS, TEMPORARY,
13
GENERATED, SECONDARY
14
from big_table.big_table;
Table created. (10,000,000 rows)
Partitioning
SQL> create table big_table2
2 ( ID, OWNER, OBJECT_NAME, SUBOBJECT_NAME,
3
OBJECT_ID, DATA_OBJECT_ID,
4
OBJECT_TYPE, CREATED, LAST_DDL_TIME,
5
TIMESTAMP, STATUS, TEMPORARY,
6
GENERATED, SECONDARY )
7 partition by hash(id)
8 (partition part_1 tablespace big2,
9
partition part_2 tablespace big2,
10
partition part_3 tablespace big2,
11
partition part_4 tablespace big2,
12
partition part_5 tablespace big2,
13
partition part_6 tablespace big2,
14
partition part_7 tablespace big2,
15
partition part_8 tablespace big2
16 )
17 as
18 select ID, OWNER, OBJECT_NAME, SUBOBJECT_NAME,
19
OBJECT_ID, DATA_OBJECT_ID,
20
OBJECT_TYPE, CREATED, LAST_DDL_TIME,
21
TIMESTAMP, STATUS, TEMPORARY,
22
GENERATED, SECONDARY
23
from big_table.big_table;
Table created.
Partitioning
SQL> select b.tablespace_name,
2
mbytes_alloc,
3
mbytes_free
4
from ( select round(sum(bytes)/1024/1024) mbytes_free,
5
tablespace_name
6
from dba_free_space
7
group by tablespace_name ) a,
8
( select round(sum(bytes)/1024/1024) mbytes_alloc,
9
tablespace_name
10
from dba_data_files
11
group by tablespace_name ) b
12
where a.tablespace_name (+) = b.tablespace_name
13
and b.tablespace_name in ('BIG1','BIG2')
14 /
TABLESPACE MBYTES_ALLOC MBYTES_FREE
---------- ------------ ----------BIG1
1496
344
BIG2
1496
344
Partitioning
We would need a lot of free space (resource) to
move this table, you need 2 copies
SQL> alter table big_table1 move;
alter table big_table1 move
*
ERROR at line 1:
ORA-01652: unable to extend temp segment by 1024 in tablespace BIG1
Partitioning
We cannot move this table, but
SQL> alter table big_table2 move;
alter table big_table2 move
*
ERROR at line 1:
ORA-14511: cannot perform operation on a partitioned object
Partitioning
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
SQL> alter table
Table altered.
Partitioning
Of course, we would likely automate this process
SQL> begin
2
for x in ( select partition_name
3
from user_tab_partitions
4
where table_name = 'BIG_TABLE2' )
5
loop
6
execute immediate
7
'alter table big_table2 move partition ' ||
8
x.partition_name;
9
end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
Partitioning
Took less free space
If something failed, we only lost 1/8th the work (8
partitions)
You would need less UNDO space at any single
point in time
You can spread the work out over many days
Reduced contention
Instead of 1 index with 1 hot block, you have N
indexes with 1 hot block each
Instead of one set of freelists (be they ASSM or
MSSM), you have N.
Partitioning - Schemes
Partitioning
Composite Partitioning
Range
List
Hash
Range
11gr1
9i
8i
List
11gr1
11gr1
11gr1
Hash
11gr2
11gr2
11gr2
Indexing
Local Indexes
Two types are defined
Local Indexes
Local Indexes
ops$tkyte%ORA11GR2> create index local_prefixed on partitioned_table (a,b) local;
Index created.
ops$tkyte%ORA11GR2> set autotrace traceonly explain
ops$tkyte%ORA11GR2> select * from partitioned_table where a=1 and b=2;
Execution Plan
---------------------------------------------------------Plan hash value: 1622054381
---------------------------------------------------------------------------------| Id | Operation
| Name
| | Pstart| Pstop |
---------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
| |
|
|
|
1 | PARTITION RANGE SINGLE
|
| |
1 |
1 |
|
2 |
TABLE ACCESS BY LOCAL INDEX ROWID| PARTITIONED_TABLE | |
1 |
1 |
|* 3 |
INDEX RANGE SCAN
| LOCAL_PREFIXED
| |
1 |
1 |
---------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - access("A"=1 AND "B"=2)
Note
----- dynamic sampling used for this statement (level=2)
Local Indexes
ops$tkyte%ORA11GR2> drop index local_prefixed;
Index dropped.
ops$tkyte%ORA11GR2> create index local_nonprefixed on partitioned_table (b) local;
Index created.
ops$tkyte%ORA11GR2> select * from partitioned_table where a=1 and b=2;
Execution Plan
---------------------------------------------------------Plan hash value: 904532382
--------------------------------------------------------------------------------| Id | Operation
| Name
|| Pstart| Pstop |
--------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
||
|
|
|
1 | PARTITION RANGE SINGLE
|
||
1 |
1 |
|* 2 |
TABLE ACCESS BY LOCAL INDEX ROWID| PARTITIONED_TABLE ||
1 |
1 |
|* 3 |
INDEX RANGE SCAN
| LOCAL_NONPREFIXED ||
1 |
1 |
--------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - filter("A"=1)
3 - access("B"=2)
Global Indexes
Partitioned using a scheme different from table
Statistics
Partitioning
Discuss Statistics
Local
Global
Gathering Statistics
Strategy For New Databases
Create tables
Optionally Run (or explain) queries on empty tables
Load data
Gather statistics
Gathering Statistics
Incremental Statistics
One of the biggest problems with large tables is keeping the
schema statistics up to date and accurate
This is particularly challenging in a Data Warehouse where
tables continue to grow and so the statistics gathering time
and resources grow proportionately
To address this problem, 11.1 introduced the concept of
incremental statistics for partitioned objects
This means that statistics are gathered for recently modified
partitions
Gathering Statistics
The Concept of Synopses
It is not possible to simply add partition statistics together to
create an up to date set of global statistics
This is because the Number of Distinct Values (NDV) for a
partition may include values common to multiple partitions.
To resolve this problem, compressed representations of the
distinct values of each column are created in a structure in
the SYSAUX tablespace known as a synopsis
Gathering Statistics
Synopsis Example
Object
Column Values
NDV
Partition #1
1,1,3,4,5
Partition #2
1,2,3,4,5
NDV by addition
WRONG
NDV by Synopsis
CORRECT
Compression
Fewer IOs
Buffer Cache efficiency
No impact on reads
Overhead
Inserts are
again
uncompressed
Free Space
Uncompressed
Compressed
FIRST_NAME LAST_NAME
John
Doe
Jane
Doe
John
Smith
Jane
Doe
Initially Uncompressed
Block
Header
1JohnDoe 2Jane
Doe 3JohnSmith 4
Jane Doe
Free Space
FIRST_NAME
LAST_NAME
John
Doe
Jane
Doe
John
Smith
Jane
Doe
Jack
Smith
Local
Symbol Table
Compressed
Block Block
Header
John=|Doe=|Jane=|Smith=
1
2 3
4
1JohnDoe
2Jane
Doe
5Jack
3JohnSmith 4
Jane Doe
Free Space
Free Space
Compressed Block
Header
Header
John=|Doe=|Jane=|Smith=
1JohnDoe 2Jane
Doe 3JohnSmith 4
Jane Doe 5Jack
Smith Free Space
Local
Symbol Table
1
2 3
4
1JohnDoe
2Jane
Doe
5Jack
3JohnSmith 4
Jane Doe
Free Space
Free Space
More Data
Per Block
Purging
Purging
Best facilitated by partitioning
Attaching the new data: Once the new data is loaded and
processed, the table it is in is exchanged with an empty
partition in the partitioned table, turning this newly loaded
data in a table into a partition of the larger partitioned table.
Sliding Window
ops$tkyte@ORA11GR2> CREATE TABLE partitioned
2 ( timestamp date,
3
id
int
4 )
5 PARTITION BY RANGE (timestamp)
6 (
7 PARTITION fy_2004 VALUES LESS THAN
8 ( to_date('01-jan-2005','dd-mon-yyyy') ) ,
9 PARTITION fy_2005 VALUES LESS THAN
10 ( to_date('01-jan-2006','dd-mon-yyyy') )
11 )
12 /
Table created.
ops$tkyte@ORA11GR2> insert into partitioned partition(fy_2004)
2 select to_date('31-dec-2004',dd-mon-yyyy)-mod(rownum,360), object_id
3 from all_objects
4 /
72090 rows created.
ops$tkyte@ORA11GR2> insert into partitioned partition(fy_2005)
2 select to_date('31-dec-2005',dd-mon-yyyy)-mod(rownum,360), object_id
3 from all_objects
4 /
72090 rows created.
Sliding Window
Sliding Window
To archive to
Sliding Window
ops$tkyte@ORA11GR2> create table fy_2006 ( timestamp date, id int );
Table created.
ops$tkyte@ORA11GR2> insert into fy_2006
2 select to_date('31-dec-2006',dd-mon-yyyy)-mod(rownum,360), object_id
3 from all_objects
4 /
72097 rows created.
ops$tkyte@ORA11GR2> create index fy_2006_idx on fy_2006(id) nologging
2 /
Index created.
Data to be loaded
Sliding Window
Sliding Window
Sliding Window
STATUS
-------VALID
VALID
UNUSABLE
N/A
Sliding Window
Sliding Window
Same here
Sliding Window
STATUS
-------VALID
VALID
VALID
N/A
6 rows selected.
Backing Up
Backing Up
The fastest way to do
something is to not do it
Backing Up
Use Read Only Tablespaces
Backing Up
Dont do indexes
Backing Up
Use true incrementals
Backing Up
Use compression where ever available
Q&A