列中的多个列的唯一约束是否有任何区别?重复索引是否合理?

时间:2013-07-12 11:33:35

标签: sql oracle indexing oracle11g unique-constraint

在Steve O'Hearn的“SQL认证专家考试指南”中,我发现了这一段:

  

在极少数情况下,当您创建复合索引以及调用同一索引的多个约束时,需要特殊语法。例如,如果我们决定在INVOICES表中的两个列上创建复合索引,我们可以使用以下语法:

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
);

这是我的问题:

  1. 创建两个唯一约束以更改声明中的列顺序有什么意义?

  2. 我们创建了一个多列索引:“invoice_id”作为第一列,“invoice_date”作为第二列。但是我们假设我们经常运行与“invoice_date”本身相关的查询,而没有“invoice_id”参与。在“invoice_date”上创建第二个单列索引是一个好主意吗?我知道:

  3.   

    由于Oracle支持多列索引,因此很容易意外地创建“重复”索引,为DML增加开销并且无助于加速SQL执行的索引。   [Source]

    我也知道:

      

    感谢跳过扫描引用复合索引中的任何列的WHERE子句可以在其处理中调用索引。 [Steve O'Hearn]

    但我也知道:

      

    这不如简单的单列索引那么有用,它的好处各不相同,具体取决于第一列中值的唯一性。 [Steve O'Hearn]

    因此,我们假设我们很少在此表上使用DML命令,并假设我们与SELECT的WHERE子句中的两个列分别与“index_date”或“index_id”相关。在某些情况下,创建两个索引是否合理?一个多列索引on(index_id,index_date)和第二个单列索引on(index_date)?

2 个答案:

答案 0 :(得分:4)

你的问题是:

  

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

答案是肯定的。第一个索引将用于满足以下条件的查询:

  • index_id子句
  • 中对where进行过滤
  • index_id子句中的index_datewhere进行过滤
  • index_id子句中的where进行过滤,按index_date排序

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

  • index_date子句
  • 中对where进行过滤

在这种情况下,第一个索引将

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

答案 1 :(得分:3)

你问了

  

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

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

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列(特别是如果时间元素被截断的话),所以通常我希望将索引构建为{{1无论如何。这可能允许我们使用索引压缩。

跳过扫描并不像Steve所说的那样有效:它首先探测索引的前沿,但前提是在WHERE子句中引用了复合索引中的第二列。优化程序可能会选择全速快速索引扫描以在第三列或更低列上进行搜索。如果前沿有太多不同的值,它也不会选择跳过扫描路径:另一个很好的理由是选择性地使用低柱。

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