4

我有一个有 7 列的表。

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

在这 7 列中,有 5 列是我将在我的查询的 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 中选择金额,其中 ST=0 且 DEPARTID=112 且 PERIOD='201207';
  2. 从 AG_PAYMENTS_TO_BE 中选择金额,其中 ST=0 且 PENSIONERID=123456 且 PERIOD='201207';
  3. 从 AG_PAYMENTS_TO_BE 中选择金额,其中 ST=0 且 PENSIONERID=123456 且 PERIOD='201207' 且 PAYMENTTYPE=1;
  4. 从 AG_PAYMENTS_TO_BE 中选择金额,其中 ST=0 且 DEPARTID=112 且 ST=0;
  5. 从 AG_PAYMENTS_TO_BE 中选择金额,其中 ST=0 且 PENSIONERID=123456;

等等。

4

3 回答 3

3

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

  • 前导索引列必须在查询中列出
  • 他们必须使用精确连接进行比较(即使用=、非<或)>like

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

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

但不是:

  • b = :b2

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

请注意,仅使用其中一些前导列的查询可以使用“更大”的索引。所以在上面的例子中,在 just 上的索引a是多余的,因为显示的查询可以使用在 上的索引a, b。但是,关于 just 的索引b可能很有用。

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

请注意,具有相似列的多个索引可能会导致选择错误的索引。因此,当您有许多类似的索引时,选择可能会有不利之处。解析时间也有一点开销,因为 Oracle 在选择执行计划时需要考虑更多选项。

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

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

您可能还希望amount在这些末尾添加,以便可以从索引中完全回答您的查询,从而为您节省表查找。如果这些列是其他表的外键,您可能还需要更多索引,以防止锁定问题

于 2013-04-02T14:29:37.603 回答
2

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

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

  1. 显然,PAYMENTTYPE 和 ST 字段每个最多可保存10 19 个不同的值,如果我们牢记您的预期数据量(约 4 亿行),这是非常不具选择性的,因此它们不会对您有太大帮助。

  2. 然而,他们可能会成为很好的候选人list partitioning

  3. 我还会考虑将 PERIOD CHAR(6 CHAR) 切换到 DATE 并在 period+st/paymenttype 上创建一个复合范围列表分区。

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

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

于 2013-04-02T14:00:57.860 回答
1

我认为您应该创建一些组合索引(例如('ST' and 'PERIOD')和('ST' and 'PENSIONERID')。这将加快您的大多数示例查询......

于 2013-04-02T12:48:38.707 回答