【问题标题】:Index needed for max(col)?max(col) 需要索引吗?
【发布时间】:2011-06-24 21:28:47
【问题描述】:

我目前正在为一种仓库解决方案进行一些数据加载。我每晚都会从生产中导出数据,然后必须加载。仓库表上没有其他更新。为了只为某个表加载新项目,我目前正在执行以下步骤:

  • 获取特定列的当前最大值 y(日志表的 id 和事件表的时间)
  • 通过类似where x > y的查询加载数据

为了避免性能问题(我每天加载大约 100 万行),我从表中删除了大多数索引(只有生产需要,仓库中不需要)。但是这样检索最大值需要一些时间......所以我的问题是:

在该列上没有索引的情况下,获取当前最大值的最佳方法是什么?我刚刚阅读了有关使用stats 的信息,但我不知道如何处理带有“timestamp with timezone”的列。在加载之前禁用索引,然后重新创建它需要很长时间......

【问题讨论】:

  • 致密友:这是 SO 的主题。这是一个关于 DBMS 编程的问题。

标签: performance oracle statistics indexing


【解决方案1】:

这段代码是用oracle写的,但是应该兼容大部分的SQL版本:

这会根据范围获取表中max(high_val)的key。

select high_val, my_key
from (select high_val, my_key
      from mytable
      where something = 'avalue'
      order by high_val desc)
where rownum <= 1

这句话的意思是:按high_val 降序对something = 'avalue' 的值排序mytable。只抓取第一行,它将为您提供所选范围内的 max(high_val) 和该表的 my_key。

【讨论】:

    【解决方案2】:

    让创建提取文件的过程也提取具有您想要的最小/最大值的单行文件。我假设该片段是在某个 cron 或调度程序上编写的,因此要求向该脚本添加最小/最大计算不应该太多;)

    如果没有,请进行全面扫描。百万行并不多,尤其是在数据仓库环境中。

    【讨论】:

      【解决方案3】:

      作为列级统计信息的一部分计算的最小值和最大值是估计值。优化器只需要它们相当接近,而不是完全准确。我当然不会相信它们是加载过程的一部分。

      每天加载一百万行并不算多。你有一个非常小的加载窗口吗?我有点难以相信您负担不起为执行最小/最大索引扫描所需的行编制索引的成本。

      但是,如果您想避免使用索引,您可能希望将最后一个最大值存储在一个单独的表中,该表作为加载过程的一部分进行维护。在表 A 中加载第 1-1000 行后,您将更新此汇总表中表 A 的行,以指示您处理的最后一行是第 1000 行。下次进入时,您将从汇总表,从 1001 开始。

      【讨论】:

      • 实际上在一个额外的表中手动管理这个听起来是个好主意......无论如何,关于创建索引的问题。数据加载到的表目前大约有 400 行。删除和重新创建索引需要很长时间...
      • @Ingo - 我并不是建议您每天都删除并重新创建索引。如果您每天只加载一百万行数据,我建议创建索引并将其保留在那里似乎不太可能导致严重的性能问题。
      • 不幸的是,负载从大约一分钟增加到近一个小时......这听起来合理吗?
      • @Ingo - 这似乎不太合理,不。您是否对需要一个小时的会话进行了跟踪?或者当时系统的 AWR/statspack 报告(假设没有太多其他事情发生)?
      • 不幸的是我没有这样做。但据我所知,在加载期间,机器上根本没有任何工作。关于痕迹:获得一个的最佳方法是什么?到目前为止,我还没有做太多 dba 的工作......对不起。不幸的是,管理员目前没有时间为我分析这个,所以我一个人在这里。与此同时,我想我会坚持你所谓的解决方案。谢谢。
      【解决方案4】:

      如果列上没有索引,DBMS唯一能在列中找到最大值的方法是全表扫描,对于大表需要很长时间。

      我想 DBMS 可以在插入、更新和删除时尝试跟踪列中的最小值和最大值(将值存储在系统目录中) - 但删除是我所知道的没有 DBMS 尝试的原因通过每行操作使统计信息保持最新。如果删除最大值,如果该列没有被索引,则查找新的最大值需要进行表扫描(如果它被索引,则索引使得查找最大值变得微不足道,因此信息不必存储在系统目录)。这就是为什么它们被称为“统计”;它们是适用值的近似值。但是当您请求“SELECT MAX(somecol) FROM sometable”时,您并没有要求统计最大值;您要求的是当前的实际最大值。

      【讨论】:

      • 听起来很合理......因为我只做插入,所以很糟糕...... ;-)
      • 那么,在加载之前禁用索引并在加载之后更新它会更好吗?如果是,怎么做?
      猜你喜欢
      • 1970-01-01
      • 2011-11-20
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多