如何提高 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) &gt;= trunc(sysdate) - 5)。

以上是关于如何提高 Oracle 中仅加载最近 5 天内修改的项目的 SQL 性能?的主要内容,如果未能解决你的问题,请参考以下文章

如何在最近 5 天内按播放次数获得 iTunes 库前 10 首歌曲?

获取目录中最近 30 天内修改的所有文件

Unix命令行:如何获取最近30天修改文件的总大小

如何从 Matlab 中的 .mat 文件中仅加载一个单元格的条目?

在 USB 密钥上的压缩存档中获取过去 5 天内修改的文件

如何查询最近 30 天内添加的产品(HSQLDB)