1

我有一张非常大的桌子,有几十列和很多行。让我们将此表称为 FT。每天我都会运行一个脚本,从 FT 表中读取数据,执行一些计算,然后更新一个较小的表(表 FA),用于生成报告。

更新 FA 的查询类似于:

INSERT INTO FA (A, B, C) 
    (SELECT sum(X), sum(x) * sum(y), sum(x) + sum(z)) group by..

由于我多次使用 sum(x),如果我创建一个包含 sum(x)、sum(y) 和 sum(z) 的临时表并使用它来更新我的 FA 表会更快吗?

4

4 回答 4

2

我知道的每个 db 都对这种类型进行了优化,因此这些值只计算一次。

如果您不确定查看当前查询的执行计划和读取以及更改为临时表查询。

于 2010-08-18T19:59:33.713 回答
2

作为一般经验法则,从磁盘检索数据所花费的时间是数据库执行的最慢操作(尤其是在大表上)

相比之下,我希望像这些相对直接的算术运算可以忽略不计。

于 2010-08-18T20:35:34.140 回答
0

对您的查询进行基准测试:

insert into fa (a, b, c)
select sum_x, sum_x * sum_y, sum_x * sum_z
  from (select sum(x) as sum_x, sum(y) as sum_y, sum(z) as sum_z
          from my_table
         group by my_grouping_columns)

我强烈怀疑甲骨文必须首先构建中间集 - 无论如何分组的总和 - 然后将其转换为最终结果集,无论如何。

强制Oracle将中间结果集具体化为全局临时表肯定不会更容易或更快;您在没有充分理由的情况下添加直接路径 I/O。也就是说,如果中间结果集的构建和多次插入使用成本很高,那么将其具体化到临时表中可能是值得的。

于 2010-08-19T04:58:10.337 回答
0

考虑到您已经用data-warehouseand标记了这篇文章datamart,我只能假设您的 FT 表是某种事实,并且查询看起来像:

select 
    CalendarMonth
  , sum(x) as Tot_1 
  , sum(x) * sum(y) as Tot_2
  , sum(x) + sum(z) as Tot_3
from FT         as f
join dimDate    as d on d.DateKey    = f.DateKey
join dimUser    as u on u.UserKey    = f.UserKey
join dimProduct as p on p.ProductKey = f.ProductKey
where CalendarYear between 2008 and 2010
  and Country = 'United States'
  and ProductCategory = 'Cool Gadget'
  and UserGender = 'Female'
group by CalendarMonth ;

这正是事实表中度量的聚合应该是什么样子的。

现在,出于报告目的,您似乎有一个汇总表 (FA) 来加快报告速度。我只能猜测仓库是在夜间加载的,并且您的查询有时会在早上,工作时间之前准备聚合,因此它每天运行一次 - 或者至少应该运行一次。如果此查询运行时间过长,请考虑在聚合表 (FA) 中添加几个关键字段(通常是 DateKey),然后定期更新 FA 表。

例如,如果您每天有 10,000 笔销售,则上述查询每月总计约 300,000 行。如果聚合表每天聚合,则每天更新一次表需要 10,000 行的总和,而报表每月只需 30 行的总和。

总而言之,为了加速事实聚合查询关注聚合的行数——而不是聚合函数。此外,请确保维度表在查询的 WHERE 子句中提到的列上具有索引。

诚然,我可能在这里假设太多,所以这可能有帮助,也可能没有帮助。

于 2010-08-19T12:14:08.453 回答