【问题标题】:Very bad performance of UNION select query in RedShift / ParAccelRedShift / ParAccel 中 UNION 选择查询的性能非常差
【发布时间】:2013-11-19 19:58:07
【问题描述】:

我有两个红移表:

  • tbl_current_day - 大约 450 万行
  • tbl_previous_day - 大约 450 万行,数据与 tbl_current_day 完全相同

除此之外,我还有一个名为 qry_both_days 的视图,定义如下:

CREATE OR REPLACE qry_both_days AS 
SELECT * FROM tbl_current_day
UNION SELECT * FROM tbl_previous_day;

当我在其中一个单独的表上运行查询时,我得到了预期的非常好的性能。 例如,以下查询运行 5 秒:

select count(distinct person_id) from tbl_current_day;
-- (person_id is of type int)

解释计划:

 XN Aggregate  (cost=1224379.82..1224379.82 rows=1 width=4)
   ->  XN Subquery Scan volt_dt_0  (cost=1224373.80..1224378.61 rows=481 width=4)
         ->  XN HashAggregate  (cost=1224373.80..1224373.80 rows=481 width=4)
               ->  XN Seq Scan on tbl_current_day  (cost=0.00..979499.04 rows=97949904 width=4)

请注意,宽度应该是 4 个字节,因为我的列是 int 类型。

但是,当我在 qry_both_days 上运行相同的查询时,查询的运行速度会慢 20 倍,而我预计它的运行速度应该会慢 2 倍超过两倍的行数:

select count(distinct person_id) from qry_both_days;

解释计划:

 XN Aggregate  (cost=55648338.34..55648338.34 rows=1 width=4)
   ->  XN Subquery Scan volt_dt_0  (cost=55648335.84..55648337.84 rows=200 width=4)
         ->  XN HashAggregate  (cost=55648335.84..55648335.84 rows=200 width=4)
               ->  XN Subquery Scan qry_both_days  (cost=0.00..54354188.49 rows=517658938 width=4)
                     ->  XN Unique  (cost=0.00..49177599.11 rows=517658938 width=190)
                           ->  XN Append  (cost=0.00..10353178.76 rows=517658938 width=190)
                                 ->  XN Subquery Scan "*SELECT* 1"  (cost=0.00..89649.20 rows=4482460 width=190)
                                       ->  XN Seq Scan on tbl_current_day  (cost=0.00..44824.60 rows=4482460 width=190)
                                 ->  XN Subquery Scan "*SELECT* 2"  (cost=0.00..90675.00 rows=4533750 width=187)
                                       ->  XN Seq Scan on tbl_previous_day  (cost=0.00..45337.50 rows=4533750 width=187)

问题:宽度现在是 190,而不是应该的 4 个字节!!! 有人知道如何让 RedShift 只选择 UNION SELECT 上的相关列吗?

谢谢!

【问题讨论】:

  • 由于前一天表和当天表中的数据应该是不相交的,因此您应该能够通过使用 UNION ALL 获得额外的性能提升,这将跳过 UNION 操作的 DISTINCT 步骤。跨度>

标签: amazon-redshift paraccel


【解决方案1】:

UNION 本身使用会删除重复的行,例如,根据 SQL 规范,使用隐含的 DISTINCT

这意味着需要更多的处理来准备输出。

如果您不想要DISTINCT 结果,那么您应该始终使用UNION ALL 以确保数据库没有检查潜在的欺骗。

【讨论】:

  • 从经验上看,这实际上似乎是真正的问题,至少截至 2015 年第三季度。我正在创建两个完整的、相同宽度的表的联合视图,其中一个包含 ~1B 行,并且一个包含约 8B 行...使用 SELECT * [..] UNION SELECT [..]SELECT * [..] UNION ALL SELECT * [..] 的视图之间的差异非常明显。 UNION ALL 比单表 SELECT 贵约 5%,而 UNION 贵约 150 倍。这是带有注释的 EXPLAIN 输出的要点 - gist.github.com/slpsys/5e43d8237fd8aa924015
【解决方案2】:

您的视图创建为SELECT *,因此它始终查询所有列来为视图创建数据。 然后使用另一个SELECT,只返回视图中请求的列。

如果您选择的列数量有限(例如始终使用的两三个集合),我会为每个列集合创建一个单独的视图。

另一种方法(甚至比以前更不优雅)是调用每个视图,以便其名称说明包含哪些列(假设已排序并用'__'分隔) - 就像qry_both_days__age__name__person_id。然后,在每次查询之前,检查所需的视图是否存在,如果不存在,则创建它。

【讨论】:

  • 感谢您的建议。但是,我无法提前告诉用户将查询哪些列。有没有其他方法可以在 RedShift 中编写 UNION SELECT 使其仅获取相关列?
  • @diemacht,看看我的答案插件:)
  • 这种类型的列选择优化是我有时更喜欢从更高级别的表示(例如,领域特定语言 (DSL))生成代码的查询的原因。当您考虑 CTE 和多级聚合/汇总时,通过多个视图(或子查询)层管理许多自定义列列表变得缓慢且容易出错。
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多