【问题标题】:Two sql for Sorted timestamp date两个用于排序时间戳日期的 sql
【发布时间】:2012-03-29 21:15:00
【问题描述】:

我有 98w 行数据。当我想用 pub_time 对数据进行排序时,我发现了一件有趣的事情。

这里是 SQL:

select * 
from t_p_blog_article_info t  
order by t.pub_time desc

花费 19 秒。

select * 
from t_p_blog_article_info t 
where t.pub_time > to_date( '1900-01-01 01:00:00', 'yyyy-mm-dd   hh24:mi:ss ')  
order by t.pub_time desc

花费 0.2 秒。

我想知道,为什么?

【问题讨论】:

  • pub_time 列上是否有索引?
  • 只是猜测,但 t.pub_time 可以为 NULL 吗?
  • 显然你的 where 子句过滤掉了很多记录,为什么? null 值,或者只是在 01.01.1900 之前具有错误时间值的条目
  • 是的,它在pub_time上有索引,我的同事使用oracle explan时间工具发现,第一次查询没有使用索引,它查询了195M数据!!

标签: sql performance oracle datestamp


【解决方案1】:

你的桌子上可能有一个关于 pub_time 的索引。

因此,第二个查询可以利用该索引只返回指定日期之后非空日期的记录,而第一个查询必须查询整个表。

【讨论】:

  • 是的,我在 pub_time 上有索引,但为什么第一个查询不使用索引?
  • 虽然,正确地说,两个查询最终都必须查询整个表,因为它们都有 SELECT *大概 都返回所有行。 (至少,如果第二个查询返回的行数更少,我怀疑 OP 会问这个问题。)
  • @sarowlwp:索引不包含空值,因此如果pub_time 可以为空(即使它实际上从未为空),则其上的索引对于 WHERE-子句不排除为空的记录。
  • 因为您的日期列中可能有空值 - Oracle 中的普通索引不记录空值,因此不能单独使用索引对可能包含空值的列进行排序。
  • 但是该列是否定义为不可为空?
【解决方案2】:

有多种可能性。您可能会在 pub_time 中过滤掉大量具有无效/空日期的行,但我怀疑您不会注意到/提及其中的大量行。

让我印象深刻的三件事是:

1 - 您有一个涉及 pub_time 的索引或复合索引,并且您的 where 子句中的限制正在触发使用不同的访问路径

2 - 当您运行第一个查询时,您没有可用于优化器的统计信息。运行第二个查询时,由于运行第一个查询时发生的一些信息缓存,选择了更好的访问路径。这可以通过多次运行第一个查询并查看是否有显着的性能改进来验证。

3 - 与第一点类似,优化器可能只是根据 where 子句的含义选择更好的访问路径。或许给出不必处理 null/invalid 值的提示就足够了 - 您的系统可能会避免一次或多次全表扫描以清除无效/null pub_times。

查明此类事情的原因正在迅速成为一种经验冒险 - 如果不知道您的平台和版本,我很难说更多。从标签中我认为您正在使用 oracle,在这种情况下,您应该能够使用某种形式的“解释查询”或“解释计划”工具来更好地了解正在发生的事情。有关 oracle 优化器的更多信息,请参阅http://docs.oracle.com/cd/B10500_01/server.920/a96533/optimops.htm(这是针对 Oracle 9i v9.2,但它对与版本无关的概念有很好的解释)

【讨论】:

    猜你喜欢
    • 2014-05-22
    • 1970-01-01
    • 2022-01-23
    • 2019-10-24
    • 2022-11-11
    • 2019-11-01
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多