【问题标题】:Index to create when the query has to compare two columns当查询必须比较两列时创建的索引
【发布时间】:2022-11-17 03:27:25
【问题描述】:

我有以下执行时间较长的查询,其中当前索引是在 ENTER_TIME 和 EXIT_TIME 的各个列上创建的,并且 location_id 是两个表上的 primary_key。

数据库服务器:Oracle Database 19c Standard Edition 2

版本:19.11.0.0.0

SELECT
    trp.location,
    trp.enter_time,
    trp.exit_time
    SUM(TIMEDIFF(trp.enter_time,trp.exit_time)) AS stay_time
FROM
    trip_route_point trp
INNER JOIN 
    location l ON trp.location_id = l.location_id
WHERE 
    trp.enter_time BETWEEN '20221010070000' AND '20221108070000' 
    AND trp.exit_time IS NOT NULL 
    AND trp.exit_time >= trp.enter_time
GROUP BY 
    trp.location_id
HAVING 
    SUM(TIMEDIFF(trp.enter_time, trp.exit_time)) > 0 
ORDER BY 
    stay_time DESC

trip_route_point 表中有 250 万行的查询性能为 3 秒。

我怀疑 trp.exit_time >= trp.enter_time 条件没有使用索引。

从执行计划我可以看到查询需要全表扫描。

请告知用于提高查询性能的最佳索引

【问题讨论】:

  • 包括执行计划、表和索引,因为文本可能会有帮助 - 请参阅How to describe performance issue in relational database?。进入/退出时间真的是字符串,而不是日期或时间戳吗?你的 timediff 函数是如何操纵这些的?你为什么要加入location,因为你似乎不再提到它了?
  • explain 会给你一个执行计划,它会告诉你为什么它很慢。也就是说,(exit_time, enter_time)(enter_time) 应该涵盖您的基础。虽然它可能是order by
  • 如果数据尊重exit_time和entry_time的语义,对于not null exit_time条件trp.exit_time >= trp.enter_time很可能永远为真,所以如果DB认为匹配行的比例足够大,全扫描是可能更有效率。
  • AND trp.exit_time IS NOT NULL 那里太多了。您可以将其删除。

标签: sql database oracle indexing


【解决方案1】:

Is not null 对我来说往往表现不佳。由于您已经将该列限定为 > trp.enter_time,因此无论如何您都不会返回空结果。尝试删除 is not null。

【讨论】:

    【解决方案2】:

    “trp.enter_time BETWEEN '20221010070000' AND '20221108070000'”:隐藏在该表达式后面的隐式转换可能会使 enter_time 列上的任何索引的使用无效。
    您应该发布所涉及列的数据类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多