如果确实需要,可以在表上创建多个索引

时间:2013-04-02 12:34:01

标签: oracle indexing

我有一个包含7列的表格。

它将包含大量的数据 - 每月将添加超过170万条记录。

在这7列中,我将在不同组合中对此表的查询的WHERE子句中使用这些列。

为这些可能的组合创建不同的索引是否可以?

我问这个问题,因为如果我这样做,这张桌子上会有超过10个索引,我不确定这是不是一个好主意。

另一方面,我害怕查询没有索引的大量数据表。

这是表格:

CREATE TABLE AG_PAYMENTS_TO_BE  
(
  PAYMENTID NUMBER(15, 0) NOT NULL  
, DEPARTID NUMBER(3,0)  
, PENSIONERID NUMBER(11, 0) NOT NULL  
, AMOUNT NUMBER(6, 2)  
, PERIOD CHAR(6 CHAR)  
, PAYMENTTYPE NUMBER(1,0)  
, ST NUMBER(1, 0) DEFAULT 0   
, CONSTRAINT AG_PAYMENTS_TO_BE_PK PRIMARY KEY  
  (  
    PAYMENTID  
  )  
  ENABLE  
);

可能的查询:

  1. 从AG_PAYMENTS_TO_BE中选择AMOUNT,其中ST = 0且DEPARTID = 112 AND PERIOD ='201207';
  2. 从AG_PAYMENTS_TO_BE选择AMOUNT,其中ST = 0且PENSIONERID = 123456 AND PERIOD ='201207';
  3. 从AG_PAYMENTS_TO_BE中选择AMOUNT,其中ST = 0且PENSIONERID = 123456 AND PERIOD ='201207'AND PAYMENTTYPE = 1;
  4. 从AG_PAYMENTS_TO_BE中选择AMOUNT,其中ST = 0且DEPARTID = 112且ST = 0;
  5. 从AG_PAYMENTS_TO_BE中选择AMOUNT,其中ST = 0且PENSIONERID = 123456;
  6. 等等。

3 个答案:

答案 0 :(得分:3)

暂时忽略索引跳过扫描*,以便查询使用索引:

  • 必须在查询
  • 中列出主要索引列
  • 必须使用精确联接进行比较(即使用=,而不是<>like

例如,(a, b)上具有复合索引的表可以在以下查询中使用该索引:

  • a = :b1 and b >= :b2
  • a = :b1

但不是:

  • b = :b2

因为列b列在索引的第二位。 *在某些情况下,可以通过index skip scan在这种情况下使用索引。这是跳过索引中的前导列的位置。然而,第一列需要相对较少的不同值,这种情况并不经常发生(根据我的经验)。

请注意,只使用其中某些前导列的查询可以使用“更大”的索引。因此,在上面的示例中,仅a的索引是多余的,因为显示的查询可以使用a, b上的索引。仅b的索引可能会有用。

添加的索引越多,插入/更新/删除的速度就越慢,因为索引必须与表保持同一时间。因此,您的目标应该是保持索引数量下降,除非添加新索引有显着的查询优势。这是您必须在您的环境中衡量的,以确定确切的成本/收益。

请注意,具有相似列的多个索引可以导致wrong index being selected。因此,当您有许多类似的索引时,选择可能存在缺点。解析时间也略有开销,因为Oracle在选择执行计划时有更多选择。

查看您的查询我相信您只需要索引:

  • st, departid, period
  • st, pensionerid, period

您可能希望在这些内容的末尾添加amount,这样您的查询就可以从索引中得到完全回答,从而节省了表查找。如果这些列是其他表的外键to prevent locking issues

,则可能还需要其他索引

答案 1 :(得分:2)

这个决定很大程度上取决于每列中不同值的预期数量,从而取决于每个可能指数的选择性。

在做决定时我会考虑的事情:

  1. 显然,PAYMENTTYPE&amp; ST字段最多可以容纳 10 19个不同的值,如果我们记住您预期的数据量(~400M行),这是非常不可选择的,因此它们对您没有多大帮助。

  2. 但是,他们可能会成为list partitioning的合适人选。

  3. 我还想到将PERIOD CHAR(6 CHAR)切换到DATE并在句点+ st / paymenttype上创建复合范围列表分区。

  4. DEPARTID - 如果你有数百个部门,那么它可能是一个索引候选者,但如果只有几十个 - 那么可能整个扫描的执行速度会更快。

  5. PENSIONERID似乎是一个高选择性字段,因此我会考虑在其上创建一个单独的索引,并将其包含在PERIOD + PENSIONERID的复合索引中(按该字段顺序)。

答案 2 :(得分:1)

我认为你应该创建一些组合索引(例如('ST'和'PERIOD')和('ST'和'PENSIONERID')。这将加速你的大部分样本查询......