Redshift可以使用sortkey和连接表来避免全表扫描

时间:2016-06-03 14:32:55

标签: sql amazon-redshift

我有一张非常大的桌子" event"在Redshift和一个小得多的桌子" d_date"代表日期。 Redshift将在"事件"上运行全表扫描。对于下面的SQL,除非我取消注释注释部分。表事件将date_id作为其排序键。

为什么Redshift没有发现它首先扫描d_date然后通过匹配值来限制事件表扫描要便宜得多?

select d_date.date_id, count(*)
from d_date
join event on d_date.date_id = event.date_id
where d_date.sqldate > '2016-06-03'
/* without this the query will do a full table scan and run very slow */
/* and d_date.date_id > 20160603 */
group by 1;

这是EXPLAIN输出:

QUERY PLAN
XN HashAggregate  (cost=19673968.12..19673971.77 rows=1460 width=4)
->  XN Hash Join DS_DIST_ALL_NONE  (cost=78.63..18758349.28 rows=183123769 width=4)
    Hash Cond: ("outer".date_id = "inner".date_id)
    ->  XN Seq Scan on event  (cost=0.00..7523125.76 rows=752312576 width=4)
    ->  XN Hash  (cost=74.98..74.98 rows=1460 width=4)
          ->  XN Seq Scan on d_date  (cost=0.00..74.98 rows=1460 width=4)
                Filter: (sqldate > '2016-06-03'::date)

在部分取消注释的情况下,表格阶段将显示为:

    ->  XN Seq Scan on event  (cost=0.00..928.32 rows=74266 width=4)

我有两个表的VACUUMed和ANALYZEd,我设置了主键和外键。

1 个答案:

答案 0 :(得分:4)

Amazon Redshift文档专门针对Amazon Redshift Best Practices for Designing Queries中的这一主题:

  

如果可能,请使用基于查询中最大表的主排序列的WHERE子句来限制数据集。然后,查询计划程序可以使用行顺序来帮助确定哪些记录符合条件,因此它可以跳过扫描大量磁盘块。如果没有这个,查询执行引擎必须扫描整个表。

     

添加谓词以过滤参与连接的表,即使谓词应用相同的过滤器也是如此。查询返回相同的结果集,但Amazon Redshift能够在扫描步骤之前过滤连接表,然后可以有效地跳过这些表中的扫描块。

     

例如,假设您要加入SALESLISTING以查找12月之后列出的门票的门票销售,按卖家分组。两个表都按日期排序。以下查询将表格加入其公用密钥,并过滤大于12月1日的listing.listtime值:

select listing.sellerid, sum(sales.qtysold)
from sales, listing
where sales.salesid = listing.listid
and listing.listtime > '2008-12-01'
group by 1 order by 1;
  

WHERE子句不包含sales.saletime的谓词,因此强制执行引擎扫描整个SALES表。如果您知道过滤器会导致参与连接的行数减少,那么也要添加该过滤器。以下示例显着缩短了执行时间:

select listing.sellerid, sum(sales.qtysold)
from sales, listing
where sales.salesid = listing.listid
and listing.listtime > '2008-12-01'
and sales.saletime > '2008-12-01'
group by 1 order by 1;