1

我们有一些存储时态数据的表,这些表具有由 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:00 进行预测时,为这个 id/day 组合找到的最后一个条目的 create_at 更改为上午 9:59,并且新计算的值与 kill_at 时间戳“31.12.2999”一起存储。

此表上的典型查询是:

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)作为该表的唯一(唯一)索引。但是当我使用查询 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 中看到的。这是该语句的唯一执行计划。但是当我让我的客户展示解释计划时,搜索列有时是 1 或 3。但当我们的应用程序运行此语句时,它永远不会是 3。

4

1 回答 1

1

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

于 2017-01-21T13:14:37.520 回答