如何提高 Oracle 中仅加载最近 5 天内修改的项目的 SQL 性能?
Posted
技术标签:
【中文标题】如何提高 Oracle 中仅加载最近 5 天内修改的项目的 SQL 性能?【英文标题】:How to improve performance of SQL in Oracle that loads only Items modified during last 5 days? 【发布时间】:2018-09-18 17:05:02 【问题描述】:我有一个表 M 有 CREATED_AT 和 MODIFIED_AT 列(日期),这个表非常大。 我需要在过去 5 天内修改或创建行:
Select * from M where MODIFIED_AT >= trunc(sysdate)-5 OR CREATED_AT >= trunc(sysdate)-5
他们没有索引,恐怕Oracle会做全扫描,它会很慢。可以创建什么样的索引来改善这一点?
MODIFIED_AT 为 Nullable,CREATED_AT 为 Not-Null。 是创建一个包含两列的索引,还是分别为每列创建两个索引更好?
更新 还有一件事:你们中的一些人建议创建基于函数的索引合并(modified_at,created_at),问题是该表中的项目很少被修改,但通常以大块创建(由系统创建,如果需要修改用户)。所以可以有很多项具有相同的 created_at 和 null modified_at。但是仍然会有一些项的 modified_at 不为空。创建位图索引有意义吗?或者任何其他方式来利用 created_at 对于表 M 中的大块项目是相同的这一事实?
另外,将索引设为 ASC 或 DESC 有什么区别吗?
【问题讨论】:
【参考方案1】:我会推荐使用union all
:
select m.*
from m
where CREATED_AT >= trunc(sysdate) - 5
union all
select m.*
from m
where MODIFIED_AT >= trunc(sysdate) - 5 and CREATED_AT < trunc(sysdate) - 5;
这可以利用m(created_at)
和m(modified_at, created_at)
上的索引。
一个简单的方法可能是确保在创建记录时设置modified_at
。然后你可以这样做:
select m.*
from m
where MODIFIED_AT >= trunc(sysdate) - 5 ;
或者另一种选择是:
select m.*
from m
where greatest(MODIFIED_AT, created_at) >= trunc(sysdate) - 5 ;
在m( greatest(MODIFIED_AT, created_at) )
上有一个基于函数的索引。这假设两列都不是NULL
。
【讨论】:
您建议为这些列创建什么样的索引?为什么我不能避免全部联合?对不起,愚蠢的问题,但我对索引的经验很少。 为什么在 union 的第二部分出现“CREATED_AT 感谢您的评论。 modified_at 可以为空,如果在创建后没有修改,则保持它为 Null 很重要,我们在其他查询中依赖它。我们不能做这样的改变 是为所有 2 列创建一个索引,还是为每列分别创建 2 个索引更好? @Alexander:您可以使用greatest(coalesce(modified_at, created_at), created_at)
来解决这个问题。这是假设created_at
不能是null
。我什至会说,如果您只有自然情况(因此在创建记录之前无法更新/修改记录),您可以简单地使用基于此表达式的索引 coalesce(modified_at, created_at)
并使用此精确表达式在查询过滤器中 (coalesce(modified_at, created_at) >= trunc(sysdate) - 5
)。以上是关于如何提高 Oracle 中仅加载最近 5 天内修改的项目的 SQL 性能?的主要内容,如果未能解决你的问题,请参考以下文章
如何在最近 5 天内按播放次数获得 iTunes 库前 10 首歌曲?