使优化器使用索引的所有列
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 查询参数进行比较。这样索引就不能正常使用了。
我们有几个 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 查询参数进行比较。这样索引就不能正常使用了。