【发布时间】: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