使优化器使用索引的所有列

make the optimizer use all columns of an index

我们有几个 table 存储时间数据,这些数据具有由 3 列组成的自然主键。示例:当天的最高温度。这是复合主键索引(按此顺序):

id number(10): the id of the timeserie.
day date: the day for which this data was reported
kill_at timestamp: the last timestamp before this data was deleted or updated.

简化逻辑:当我们在 10:00am 进行预测时,找到的这个 id/day 组合的最后一个条目将他的 create_at 更改为 9:59am 并且新的计算值以 kill_at 时间戳“31.12.2999”存储。

关于此 table 的典型查询是:

1) where id=? and day=? and kill_at=?
2) where id=? and day between (? and ?) and kill_at=?
3) where id=? and day between (? and ?)
4) where id=?

有很多我们没有预测的时间序列。这意味着我们在测量时得到一个值并且它永远不会改变。但是有一些时间序列我们预测了 200-300 次。因此,对于一个 id/day 组合,有 200 多个条目具有不同的 kill_at.

我们目前只有主键 (id, day, kill_at) 作为此 table 上的唯一(唯一)索引。但是当我使用查询 2(确切的 ID 和日期范围)进行查询时,优化器决定只使用索引的第一列。

ID  OPERATION         OPTIONS          OBJECT_NAME  OPTIMIZER  SEARCH_COLUMNS
 0  SELECT STATEMENT                                ALL_ROWS   0
 1  FILTER                                                     0
 2  TABLE ACCESS      BY INDEX ROWID   DPD                     0
 3  INDEX             RANGE SCAN       DPD_PK                  1

对于那些已经更新了 200 多次的时间序列,这确实伤害了我们。 现在我正在寻找一种方法来强制优化器使用我们索引的所有 3 列,但我找不到这方面的提示。有吗?

或者对于如何加快查询速度还有其他建议吗?我们试图减少高峰持续时间。平均持续时间较少受到关注。

让我困惑的是: 上面的执行计划是我在dba_hist_sql_plan中看到的。它是这条语句的唯一执行计划。但是当我让我的客户展示解释计划时,它有时是 search_columns 的 1 或 3。但当我们的应用程序运行此语句时,它永远不会是 3。

我们确实找到了这个问题的原因。我们使用 JPA/JDBC 并且 JDBC 日期类型没有正确建模。虽然 oracle 日期类型是秒级精度,但有人(我现在很讨厌他)在我们类型为 java.sql.Timestamp 的实体中创建了 "day" 属性(尽管它只是没有时间的日期)。 结果是 Oracle 需要强制转换(使用函数)table 中的每个条目,使其成为时间戳,然后才能与 Timestamp 查询参数进行比较。这样索引就不能正常使用了。