3

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:

  1. What's the point in creating two unique constraints changing only columns order in declaration?

  2. 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)?

4

2 回答 2

5

您问

“创建两个唯一约束仅更改声明中的列顺序有什么意义?”

没有任何意义。复合约束中的列顺序没有任何区别:

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> 

这就是备考者的问题:他们经常只是说一些东西,没有提供解释或背景。

你还问:

“在 上创建第二个单列索引是个好主意invoice_date吗?”

在不知道数据的情况下很难分辨,但我希望日期列的选择性低于 ID 列(尤其是在时间元素被截断的情况下),所以通常我希望建立一个索引(invoice_date, invoice_id)。这可能允许我们使用索引压缩。

跳过扫描并不像史蒂夫所说的那样有效:它首先探测索引的前沿,但前提是复合索引中的第二列在 WHERE 子句中被引用。优化器可能会选择完全快速索引扫描来搜索第三列或更低的列。此外,如果前沿具有太多不同的值,它也不会选择跳过扫描路径:另一个选择低列的好理由。

所以,这并不能完全回答你的问题,但我认为它确实传达了一个重要的观点:没有通用的规则来管理创建性能索引。我们需要了解数据的概况——它的值分布和数量——以及将使用该表的最重要的查询。

于 2013-07-12T14:09:29.540 回答
4

你的问题是:

在某些情况下,创建两个索引是否合理?一,多列索引,在(index_id,index_date)和第二,单列索引,在(index_date)?

答案是“是”。第一个索引将用于满足具有以下条件的查询:

  • index_idwhere子句中过滤
  • 在子句index_id中过滤index_datewhere
  • index_id在子句中过滤where和排序依据index_date

在这些情况下不会使用第二个索引。它将用于:

  • index_datewhere子句中过滤

在这种情况下不会使用第一个索引。

索引中列的顺序很重要。它们从左到右使用。所以,这两个指标很有用。但是,index_id单独使用第三个索引是没有用的,因为第一个索引已经处理了使用该索引的相同情况。

于 2013-07-12T11:40:14.397 回答