在 PLSQL 中比较日期时间的更有效方法?

Posted

技术标签:

【中文标题】在 PLSQL 中比较日期时间的更有效方法?【英文标题】:More efficient way of comparing datetimes in PLSQL? 【发布时间】:2017-03-02 17:34:11 【问题描述】:

我们在远程 Oracle 数据库中有一个 yuge 表,我主要使用它来将数据导出到我们的本地 sql server 数据库。只是为了给你一个想法,为了这篇文章的目的,我尝试做一个简单的行计数,但它在 10 分钟后没有返回值。

此表中的一列是日期时间类型(方便地称为DATETIME)。因此,例如,我的查询将获取从昨天到 8 天前的每一天的 SAUTOSMAN 列的每日 SUM

以下是我测试过的一些查询:

SELECT trunc(datetime)
  ,TransId
  ,sum(SAUTO)
  ,sum(SMAN)
  ,count(TransId)
  FROM MyTable
  WHERE     
  and trunc(DATETIME) >= trunc(sysdate)-8
  and trunc(DATETIME) < trunc(sysdate)
  group by trunc(DATETIME), TransId

还有:

SELECT 
CAST( to_char(DATETIME,'YYYYMMDD') AS int )
,TransId
,sum(SAUTO)
,sum(SMAN)
,count(TransId)
FROM MyTable
WHERE     
CAST( to_char(DATETIME,'YYYYMMDD') AS int ) >= CAST( to_char(sysdate,'YYYYMMDD') AS int ) - 8
and CAST( to_char(DATETIME,'YYYYMMDD') AS int ) < CAST( to_char(sysdate,'YYYYMMDD') AS int )
group by CAST( to_char(DATETIME,'YYYYMMDD') AS int ), TransId

两者都返回数据(尽管后者要慢得多),但必须有一种更有效的方法来检查这一点。另外,DBA 告诉我,DATETIME 列使用了分区修剪,如果有帮助的话。

最后,我只有对该表的读取权限,所以请不要对表架构改进提出任何建议。你只会浪费时间和精力。

谢谢。

【问题讨论】:

【参考方案1】:

“DBA 告诉我 DATETIME 列使用了分区修剪”

所以表是由DATETIME 分区的。在这种情况下,在 WHERE 子句中截断该列是一个非常糟糕的主意,因为这将禁用分区修剪(分区键是 DATETIME 而不是 trunc(DATETIME)

所以这对你来说应该更快:

  SELECT trunc(datetime)
       ,TransId
       ,sum(SAUTO)
       ,sum(SMAN)
       ,count(TransId)
  FROM MyTable
  WHERE DATETIME >= trunc(sysdate)-8
  and DATETIME < trunc(sysdate)
  group by trunc(DATETIME), TransId

【讨论】:

感谢您的回复。为什么需要+ 86399/86400?如果它可能与从今天检索数据有关,那么我已经编辑了问题;是前天到8天前的总和。 @AlexPoole - 你们都是对的。我看到&lt;= 不是&lt;。修复它 让我们停止猜测并进行一些诊断 - 这将确定是否正在发生分区修剪;运行你的查询后,你能得到执行计划吗?使用这个:select * from table(dbms_xplan.display_cursor(null, null, 'TYPICAL'))

以上是关于在 PLSQL 中比较日期时间的更有效方法?的主要内容,如果未能解决你的问题,请参考以下文章

access有效性规则 日期的比较 问题

验证由 PLSQL 中的 3 个字段组成的日期

ORA-01843 不是有效月份 - 比较日期

比较两个单元格时返回有效日期

如何将日期时间戳写入 PLSQL

在 datagridview 和表单之间传递数据的更有效方式