不同列中的大量重复 sum(x) 是不是会使 Select 变慢?

Posted

技术标签:

【中文标题】不同列中的大量重复 sum(x) 是不是会使 Select 变慢?【英文标题】:Does a lot of repeated sum(x) in different cols make a Select slower?不同列中的大量重复 sum(x) 是否会使 Select 变慢? 【发布时间】:2010-08-18 19:52:22 【问题描述】:

我有一张非常大的桌子,有几十列和很多行。让我们将此表称为 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 表会更快吗?

【问题讨论】:

不应该,但为什么不测试看看? 【参考方案1】:

我知道的每一个数据库都有这种类型的优化,所以这些值只计算一次。

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

【讨论】:

【参考方案2】:

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

我希望这些相对简单的算术运算相比之下可以忽略不计。

【讨论】:

您这么说就像一个从未意外编写过通过网络发送的两个 1m+ 行表的笛卡尔积的人。在这样的查询中几乎没有物理 I/O,但有大量逻辑 I/O,甚至更多的网络时间。【参考方案3】:

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

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 必须首先构建中间集——不管是分组的总和——然后将其转换为最终结果集,无论如何。

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

【讨论】:

【参考方案4】:

考虑到您已使用data-warehousedatamart 标记此帖子,我只能假设您的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 子句中提到的列上具有索引。

诚然,我可能在这里假设太多,所以这可能会或可能不会有帮助。

【讨论】:

以上是关于不同列中的大量重复 sum(x) 是不是会使 Select 变慢?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Postgresql 中的计算列中获取平均值?

BigQuery/SQL - 特定变体的拆分值

使用 dplyr [重复] 有条件地将一列中的值替换为另一列中的值

如果列中的不同计数达到 10,则只返回 true/false,而不是检查 spark 中的行数

根据不同列中的值删除重复项

大量数据,尝试替换一列中的分隔符但不是所有分隔符