Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

41
INDEXING STRATEGIES Sean Scott Oracle DBA, Bodybuilding.com

description

There's more to indexing than the basic "create index" statement! We'll go under the covers and look at the different types of indexes available in both Enterprise and Standard Editions, including b-tree, bitmap, reverse-key, functional, composite and partitioned; describe how to select the most appropriate type of index for a particular situation; explore storage parameters and lesser-known configuration options available to fine-tune performance; discuss methods for gathering statistics, including whether to capture histograms or not; and cover techniques for managing and maintaining a healthy library of indexes. Scripts included! 1. How to choose the appropriate type of index for a particular implementation. 2. An understanding of indexing options and storage configurations available to improve index (and database) performance. 3. Techniques for managing and maintaining the health of indexes.

Transcript of Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

Page 1: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

INDEXING STRATEGIESSean Scott

Oracle DBA, Bodybuilding.com

Page 3: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

B-TREE INDEXES

• Most common type of index

• Data is ordered within the index

• Consists of branches and leaves

Page 4: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

B-TREE INDEXES

Page 5: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

B-TREE INDEXES

• Options include

• Unique

• Descending

• Reverse Key

• Index Organized Tables

• Composite, Covering, Concatenated

• Compressed

Page 6: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

REVERSE KEY INDEXES

• Creates a “mirror image” of the key

• UTOUG would become GUOTU

• Used to spread block splits and avoid hot blocks in RAC environments

• No index range scans

• Lots of conflicting information

• Test extensively, and use with caution

Page 7: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

REVERSE KEY INDEXES

• Two implementations:

• last_updated_date in a customer order table

• Sequentially updated primary key

Page 8: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

REVERSE KEY INDEXES

• Things to watch for:

• Increase in db sequential read wait events

• Backup time increase

• Space use increase

Page 9: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

INDEX ORGANIZED TABLES

• Stores data and index in the same segment

• Must have a primary key

• Data is ordered

• Can have secondary indexes

• Useful for tables that are fully accessed

• Overflow for less-used data

Page 10: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

COMPOSITE INDEXES

• Sometimes known as covering or concatenated

• Consist of more than one column

• Leading column is important

Page 11: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

COMPOSITE INDEXES

create index test_i1 on test(col1);

create index test_i2 on test(col1, col2);

Page 12: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

COMPOSITE INDEXES

• Choosing a leading column

• High cardinality?

• Low cardinality?

• Most frequently accessed

Page 13: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

• The Poor-Man’s IOT

•Use to improve performance of select by reducing I/O

COVERING INDEXES

Page 14: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

 SELECT price_id,         price      FROM dcs_price    WHERE version_id       = :1      AND price_id           = :2;

-------------------------------------------------------------------------------------------| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |-------------------------------------------------------------------------------------------|   0 | SELECT STATEMENT            |             |     1 |    29 |     5   (0)| 00:00:01 ||*  1 |  TABLE ACCESS BY INDEX ROWID| DCS_PRICE   |     1 |    29 |     5   (0)| 00:00:01 ||*  2 |   INDEX RANGE SCAN          | DCS_PRICE_P |     2 |       |     3   (0)| 00:00:01 |-------------------------------------------------------------------------------------------

Page 15: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

create unique index dcs_price_i3      on dcs_price ( price_id, version_id, price);

-----------------------------------------------------------------------------------| Id  | Operation        | Name           | Rows  | Bytes | Cost (%CPU)| Time     |-----------------------------------------------------------------------------------|   0 | SELECT STATEMENT |                |     1 |    22 |     2   (0)| 00:00:01 ||*  1 |  INDEX RANGE SCAN| DCS_PRICE_I03 |     1 |    22 |     2   (0)| 00:00:01 |-----------------------------------------------------------------------------------

Page 16: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

COMPRESSED KEY INDEXES

• Leading columns have low cardinality

• Save space

• Improve performance

Page 17: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

BITMAP INDEXES

• Index on low cardinality data

• Take up little space

• Bitmap join

• Typically found in data warehouse environments

Page 18: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

FUNCTION BASED, INDEXED VIRTUAL

• Index on a database function (predefined, user written)

• Allows index lookups when a function is used

• Both store the derived value in the index

Page 19: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

INVISIBLE INDEXES

• Create or modify an index to be invisible

• Invisible to the optimizer

• Still maintained by the database

• Better, more reliable option than MONITORING USAGE

• Must set optimizer_use_invisible_indexes=TRUE

Page 20: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

VIRTUAL INDEXES

• Only visible to the optimizer

• Used for evaluating an indexes usefulness

Page 21: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

VIRTUAL INDEXES

SQL> create table test (col1 integer);Table created.

SQL> create index test_i1 on test(col1);Index created.

SQL> create index test_i2 on test(col1);create index test_i2 on test(col1) *ERROR at line 1:ORA-01408: such column list already indexed

Page 22: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

VIRTUAL INDEXES

SQL> create index test_i2 on test(col1) nosegment;

Index created.

SQL> select table_name, index_name, column_name from user_ind_columns where table_name = 'TEST';

TABLE_NAME INDEX_NAME COLUMN_NAME------------------------------ ------------------------------ --------------------TEST TEST_I1 COL1TEST TEST_I2 COL1

Page 23: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

CLUSTER INDEXES

• B-Tree Cluster Index

• Hash Cluster Index

• Hash clusters can exist on a single table

Page 24: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

PARTITIONED INDEXES

• Global Partitioned

• Crosses partitions

• Exists on whole table

• Local Partitioned

• Unique to each partition

• Watch out for non-partitioned indexes on partitions

Page 25: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

PARTITIONED INDEXES

• Locally partitioned indexes

• Isolate maintenance operations to a single partition• Mark unusable/invisible independently• Separate partitions into different tablespaces• Prefixed, non-prefixed• Unique indexes must include partition key• Can only exist on partitioned tables

Page 26: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

PARTITIONED INDEXES

• Globally partitioned indexes

• Can exist on non-partitioned tables

• Can be either range or hash based

• Partition maintenance can render the index unusable

• Global indexes on partitioned tables must lead with the partition key

Page 27: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

PARTITIONED INDEXES

Local partitionPartition index unusablePartition index unusablePartitions involved unusablePartition index unusableNo effect on indexNo effect on index

Global or non-partitionEntire index unusableEntire index unusableEntire index unusableEntire index unusableEntire index unusableEntire index unusable

OperationSplitMoveMergeExchangeTruncateDrop

Page 28: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

WHAT TO INDEX

• Primary keys

• Unique keys

• Foreign keys

• Columns frequently used in where, distinct, and order by clauses

• Columns often queried together

Page 29: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

Index all that should be, and no more.

Page 30: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

If in doubt, b-tree is probably safest.

Page 31: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

KEY CONSIDERATIONS

Create primary and unique keys within a create table or build the indexes and constraints separately?

The create table method is easier, but:

• Indexes don’t persist

• May break GoldenGate, replication

Page 32: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

create table test1 ( col1 integer);

create unique index test1_p on test1(col1);

alter table test1 add constraint test1_p primary key (col1) using index test1_p;

create table test2 ( col1 integer primary key);

-or-

create table test2 ( col1 integer, constraint test2_p primary key (col1));

Page 33: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

select table_name, index_name from dba_indexes where table_name like 'TEST%';

TEST2 SYS_C0015135TEST1 TEST1_P

Page 34: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

alter table test1 drop constraint test1_p; alter table test2 drop constraint SYS_C0015135;

select table_name, index_name from dba_indexes where table_name like 'TEST%';

TEST1 TEST1_P

Page 35: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

• Pick a convention and stick to it!

•tablename_p•tablename_un•tablename_in•tablename_fn•tablename_bn• ...etc

NAMING CONVENTION

Page 36: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

--------------------------------------------------------------------------------------------------------| Id | Operation" " " "" " " | Name" " " | Rows | Bytes| Cost (%CPU)| Time " |--------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT"" "" " " |" " " " | 30| 4230| 560 (1)| 00:00:07|| 1 | SORT ORDER BY" " " "" " |" " " " | 30| 4230| 560 (1)| 00:00:07|| 2 | NESTED LOOPS" " " "" " |" " " " | 30| 4230| 559 (1)| 00:00:07|| 3 | NESTED LOOPS "" "" " " |" " " " | 30| 3630| 552 (1)| 00:00:07|| 4 | NESTED LOOPS"" "" " " |" " " " | 30| 2790| 544 (1)| 00:00:07|| 5 | MERGE JOIN "" "" " " |" " " " | 30| 1290| 537 (1)| 00:00:07||* 6 | TABLE ACCESS BY INDEX ROWID " | TICKET_STATUSES" | 7| 42| 1 (0)| 00:00:01||* 7 | INDEX FULL SCAN" " "" | SYS_C0107546 | 10| | 1 (0)| 00:00:01||* 8 | SORT JOIN "" "" " " |" " " " | 35| 1295| 536 (1)| 00:00:07||* 9 | TABLE ACCESS BY INDEX ROWID " | TICKETS"" " | 35| 1295| 535 (1)| 00:00:07|| 10 | " BITMAP CONVERSION TO ROWIDS " " |" " " " | | |" " |" " || 11 | " BITMAP AND" " "" " " |" " " " | | |" " " |" " || 12 | " BITMAP MINUS" " "" " |" " " " | | |" " | " " ||* 13 | " BITMAP INDEX SINGLE VALUE" " | TICKETS1 " | | |" " | " " ||* 14 | " BITMAP INDEX SINGLE VALUE" " | IDX_TICKETS_I01 " | | |" " " | " " ||* 15 | " BITMAP INDEX SINGLE VALUE " " | TICKETS_INDEX | | |" " " |" " || 16 | TABLE ACCESS BY INDEX ROWID " | PANELS"" " | 1| 50| 1 (0)| 00:00:01||* 17 | INDEX UNIQUE SCAN " "" " | SYS_C0367234 " | 1| | 1 (0)| 00:00:01|| 18 | TABLE ACCESS BY INDEX ROWID " | USERS" " " | 1| 28| 1 (0)| 00:00:01||* 19 | INDEX UNIQUE SCAN" " "" | SYS_C0038942" | 1| | 1 (0)| 00:00:01|| 20 | TABLE ACCESS BY INDEX ROWID" "" | CUSTOMERS " " | 1| 20| 1 (0)| 00:00:01||* 21 | INDEX UNIQUE SCAN"" "" " | SYS_C8712300" | 1| | 1 (0)| 00:00:01|--------------------------------------------------------------------------------------------------------

Page 37: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

STORAGE

• Consider separating table and index tablespaces

• Specify suitable storage parameters

• PCTFREE is meaningless in indexes

•logging/nologging

• Extent and block size can be defined

• Manage backups

• Manage physical storage

Page 38: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

• Index reorganization options

•alter index rebuild

•alter index coalesce

•alter index shrink space (compact)

MAINTENANCE

Page 39: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

• Use DBMS_STATS

• Defaults are usually best: exec dbms_stats.set_global_prefs(‘METHOD_OPT’, ‘FOR ALL COLUMNS SIZE AUTO’);exec dbms_stats.reset_global_pref_defaults;

•CASCADE=TRUE

structureddata.org/2008/10/14/dbms_stats-method_opt-and-for-all-indexed-columns/

GENERATING STATISTICS

Page 40: Indexing Strategies for Oracle Databases - Beyond the Create Index Statement

• Introduced in 11g

• Allows you to create column groups

• Determines a relationship among potentially skewed data

dbms_stats.create_extended_stats(‘APP’, ‘CUSTOMERS’, ‘(BIRTHDATE, BIRTHSTONE)’);

EXTENDED STATISTICS