As I’ve been presenting in the last couple of posts on partitioning, one of the major benefits of this database option is basically the selectivity when filtering on the partition key, what we currently call partition pruning.
Now, what we’ve been experimenting with so far are simple based table. However, in the data warehousing world, things are not so simple.
One of the most common “performance fixes” that we see in DW is indexing. However, indexing is not always good, and combined with partitioning, it might prove to be a very unfortunate combination, if not done properly.
Partitioning world gives us two options in indexing:
- Local indexing
- Global indexing
Basically, a local index will behave similar to a partition table, being split into partitions and best performing within partition pruning cases.
The global index, on the other side, will behave like a regular index, with one particularity: when used, it will disable the partition pruning.
Basically, from my tests so far, global indexes and partition pruning don’t mix.
How and Which
The following section will provide you a simple tested guideline on how to mix these two database performance hacks to reap the highest value out of your implementation.
Unique indexes should be global – when we use unique indexes, the selectivity provided by them should be much higher than the one from partition selectivity
Non-unique indexes – local indexes – for more skewed data across partitions. This is perfect in combination with partition pruning.
Scenario 1: Global non-unique index
Use the table T1 created as part of post Oracle: Partition by List – Example
Create index on the date column:
SQL:
create index t1_dt on t1(c2);
Now looking at regular SQL for selecting a partition and then filtering on the date column:
select * from t1 where 1=1 and c1 in ('ACD') and c2 between trunc(sysdate) and trunc(sysdate+1);
Create local index on the date column (drop the prior created index):
SQL:
drop index t1_dt; create index t1_dt on t1(c2) local;
Now looking at same SQL for selecting a partition and then filtering on the date column:
select * from t1 where 1=1 and c1 in ('ACD') and c2 between trunc(sysdate) and trunc(sysdate+1);