Reputation: 911
In "SQL Certified Expert Exam Guide" by Steve O'Hearn I've found this paragraph:
In the rare instance when you create a composite index along with multiple constraints that call on the same index, a special syntax is required. For example, if we decide to create a composite index on both of our columns in the INVOICES table, we can use this syntax:
CREATE TABLE invoices
(
invoice_id NUMBER(11),
invoice_date DATE,
CONSTRAINT un_invoices_invoice_id UNIQUE (invoice_id, invoice_date)
USING INDEX (CREATE INDEX ix_invoices
ON invoices(invoice_id, invoice_date)),
CONSTRAINT un_invoices_invoice_date UNIQUE (invoice_date, invoice_id)
USING INDEX ix_invoices
);
And here're my questions:
What's the point in creating two unique constraints changing only columns order in declaration?
We've create one multiple-column index: "invoice_id" as first column and "invoice_date" as second column. But let's assume that we really often run queries that relate to "invoice_date" itself, without "invoice_id" participation. Would it be a good idea to create second, single column index on "invoice_date"? I know that:
Because Oracle supports multi-column indexes, it’s easy to accidently create “duplicate” indexes, indexes that add overhead to DML and do not aid in speeding-up SQL execution. [Source]
and I also know that:
Thanks to skip scanning a WHERE clause that references any columns within a composite index may invoke the index in its processing. [Steve O'Hearn]
but also I know that:
This isn't quite as beneficial as a simple one-column index, and its benefit varies, depending on the uniqueness of values in the first column. [Steve O'Hearn]
So let's assume that we rarely use DML commands on this table and let's assume that we relate to both columns in SELECT's WHERE clause as often as to "index_date" or "index_id" separately. Would it be justified, in certain situations, to create two indexes? One, multiple column index, on (index_id, index_date) and second, single column index, on (index_date)?
Upvotes: 3
Views: 3291
Reputation: 146209
You asked
"What's the point in creating two unique constraints changing only columns order in declaration?"
There isn't any point. The order of columns in a composite constraint doesn't make any difference:
SQL> select * from t23
2 /
COL1 COL
---------- ---
1 WTF
SQL> create index t23_i on t23(col1, col2);
Index created.
SQL> alter table t23 add constraint t23_uk unique (col1 , col2) using index t23_i
2 /
Table altered.
SQL> insert into t23 values (1, 'WTF')
2 /
insert into t23 values (1, 'WTF')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.T23_UK) violated
SQL> alter table t23 drop constraint t23_uk
2 /
Table altered.
SQL> alter table t23 add constraint t23_uk unique (col2, col1) using index t23_i
2 /
Table altered.
SQL> insert into t23 values (1, 'WTF')
2 /
insert into t23 values (1, 'WTF')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.T23_UK) violated
SQL>
That's the problem with exam-crammers: they often just say stuff, without providing explanation or context.
You also asked:
" Would it be a good idea to create second, single column index on
invoice_date
?"
Without knowing the data it's hard to tell, but I would expect a date column to be less selective than an ID column (especially if the time element is truncated), so generally I would expect an index to built as (invoice_date, invoice_id)
anyway. That might allows us to use index compression.
Skip-scanning doesn't quite work as Steve states: it starts by probing the leading edge of the index, but only if the second column in the composite index is referenced in the WHERE clause. The optimizer might choose a Full Fast Index Scan for searching on third columns or lower. Also it won't choose a Skip Scan path if the leading edge has too many distinct values: another good reason for leading with columns of low selectively.
So, this doesn't exactly answer your question, but I think it does convey an important point: there are no universal rules governing creating indexes for performance. We need to understand the profile of the data - its values distribution and volumes - and also the most important queries which will use the table.
Upvotes: 5
Reputation: 1269513
Your question is:
Would it be justified, in certain situations, to create two indexes? One, multiple column index, on (index_id, index_date) and second, single column index, on (index_date)?
The answer is "yes". The first index will be used to satisfy queries with conditions like:
index_id
in the where
clauseindex_id
and index_date
in the where
clauseindex_id
in the where
clause and the ordering by index_date
The second index would not be used in these circumstance. It would be used for:
index_date
in the where
clauseAnd the first index would not be used in this case.
The ordering of columns in indexes is important. They are used from the left to the right. So, these two indexes are useful. However, a third index on index_id
alone would not be useful, because the first index already takes care of the same situations where that index would be used.
Upvotes: 5