对表进行优化

sort key

当创建表时,可以指定一个或多个列当作sort key, 当数据加载到表中时,会以顺序存储。在执行查询时,query planner会使用这些信息来加速查询。

Redshift每个磁盘的块存储是1MB,每个block上保存着最大值和最小值的元数据。如果使用range查询,则根据这些最大值和最小值,能够快速跳过不需要查询的数据块。

选择sort的最佳实践:

  • 如果对某一列进行过滤查询(range,equal,filter…),将这一列当作sort key
  • 如果对某个dimension表进行join,将join的列当作sort key。

sort key的分析

  1. LINEORDER使用lo_orderdate进行查询:

    where lo_orderdate = d_datekey and d_year = 1997
    

    所以lo_orderdate适合当sort key

  2. dimensions表将主键当sort key

最后sort key的选择如下:

Table name Sort Key Distribution Style
LINEORDER lo_orderdate
PART p_partkey
CUSTOMER c_custkey
SUPPLIER s_suppkey
DWDATE d_datekey

data distribution

当加载数据到Redshift表时,Redshift根据表的distribution类型,把数据导入到每个分片上。

当执行查询时会根据查询类型做数据的重新分布或拷贝,因为有些join查询需要其他表的所有数据,这样一来肯定带来额外的I/O和网络负载,影响到整体的系统性能。这是也data redistribution的目的:

  • 将每个节点的数据分布尽量均匀。如果分布不均匀,一些节点的负载就会比其他的要高,影响查询性能。
  • 为了减少查询过程中的数据传输。如果进行join查询或聚合查询时数据已经在节点上,就不需要进行redistribution的步骤。

Distribution Styles的选择

  1. 可以使用explain来查看query plan:

    explain
    select sum(lo_revenue), d_year, p_brand1
    from lineorder, dwdate, part, supplier
    where lo_orderdate = d_datekey
    and lo_partkey = p_partkey
    and lo_suppkey = s_suppkey
    and p_category = 'MFGR#12'
    and s_region = 'AMERICA'
    group by d_year, p_brand1
    order by d_year, p_brand1;
    
    QUERY PLAN
    XN Merge (cost=1038007224737.84..1038007224738.54 rows=280 width=20)
      Merge Key: dwdate.d_year, part.p_brand1
      -> XN Network (cost=1038007224737.84..1038007224738.54 rows=280 width=20)
            Send to leader
            -> XN Sort (cost=1038007224737.84..1038007224738.54 rows=280 width=20)
                  Sort Key: dwdate.d_year, part.p_brand1
                  -> XN HashAggregate (cost=38007224725.76..38007224726.46 rows=280 
                        -> XN Hash Join DS_BCAST_INNER (cost=30674.95..38007188507.46 
                              Hash Cond: ("outer".lo_orderdate = "inner".d_datekey)
                              -> XN Hash Join DS_BCAST_INNER (cost=30643.00..37598119820.65 
                                    Hash Cond: ("outer".lo_suppkey = "inner".s_suppkey)
                                    -> XN Hash Join DS_BCAST_INNER  
                                          Hash Cond: ("outer".lo_partkey = "inner".p_partkey)
                                          -> XN Seq Scan on lineorder  
                                          -> XN Hash (cost=17500.00..17500.00 rows=56000 
                                                -> XN Seq Scan on part (cost=0.00..17500.00 
                                                      Filter: ((p_category)::text = 
                                    -> XN Hash (cost=12500.00..12500.00 rows=201200
                                          -> XN Seq Scan on supplier (cost=0.00..12500.00 
                                                Filter: ((s_region)::text = 'AMERICA'::text)
                              -> XN Hash (cost=25.56..25.56 rows=2556 width=8)
                                    -> XN Seq Scan on dwdate (cost=0.00..25.56 rows=2556 
    

    DS_BCAST_INNER表示在进行inner join时,表被broadcast到每个slice。Broadcasting 和 redistribution对查询的性能影响非常大。

    img

    解决redistribution的思路是使用KEY这种类型进行哈希分布,这样相同的值被分布到相同的slice,适合会进行join查询的列。

    每个表只能有一个distribution key,也就是说上面只能有一对fact tabledimension table能够在一起, 所以dimension table要选最大的那个。PART 是最大的dimension tablePART 使用p_partkeyjoin LINEORDER。 所以将 lo_partkey 当作LINEORDERdistribution keyp_partkey 当作 PART的distribution key。当数据加载时,两个的中joining key会分布到同一个slice。

  2. 将其他dimension表使用ALL distribution。

    由于其他表没有机会和fact table分布到同一个slice,所以使用ALL类型分布,这样所有slice上都有dimension表的副本。使用ALL时会增加存储空间和和从S3加载到redshift的时间。

    CUSTOMER, SUPPLIER, DWDATE 也会和LINEORDER表进行join查询,所以这三个表全设置为DISTSTYLE ALL。这三个表都非常小,而且不经常更新,对于加载时间和存储空间影响较小。

  3. 对其他表使用EVEN分布.

    目前所有的表使用了KEYALL分布。所以不必再使用EVEN。如果发现存储空间使用过大,可以将ALL再转为EVEN分布。


经过上面的分析后,结果如下:

Table name Sort Key Distribution Style
LINEORDER lo_orderdate lo_partkey作为KEY
PART p_partkey p_partkey作为KEY
CUSTOMER c_custkey ALL
SUPPLIER s_suppkey ALL
DWDATE d_datekey ALL

对列进行压缩

前面加载s3数据时,使用了compupdate off, 这样将不使用自动压缩(automatic compression)

压缩有两个好处:减少存储空间增加IO性能进而增加查询性能。

这里不再进行复杂的压缩算法分析,在执行copy命令时会自动选择最佳压缩方式,我们后面直接使用Redshift自动压缩