我们有几个表存储时态数据,这些数据具有由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中看到的。这是该声明的唯一执行计划。但是,当我让我的客户端显示解释计划时,对于search_columns,它有时是1或3。但是当我们的应用程序运行此Statement时,它永远不会是3。答案 0 :(得分:1)
我们确实找到了这个问题的原因。我们使用JPA / JDBC并且JDBC日期类型没有正确建模。虽然oracle日期类型具有第二精度,但有人(我现在讨厌他)制作了#34; day"我们的java.sql.Timestamp类型的实体中的属性(尽管它只是没有时间的一天)。 结果是Oracle需要在表中的每个条目上强制转换(使用函数),使其成为时间戳,然后才能与Timestamp查询参数进行比较。这样就无法正确使用索引。