当创建表时,可以指定一个或多个列当作sort key
, 当数据加载到表中时,会以顺序存储。在执行查询时,query planner会使用这些信息来加速查询。
Redshift每个磁盘的块存储是1MB,每个block上保存着最大值和最小值的元数据。如果使用range查询,则根据这些最大值和最小值,能够快速跳过不需要查询的数据块。
选择sort的最佳实践:
sort key
。LINEORDER
使用lo_orderdate
进行查询:
where lo_orderdate = d_datekey and d_year = 1997
所以lo_orderdate
适合当sort key
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 |
当加载数据到Redshift表时,Redshift根据表的distribution类型,把数据导入到每个分片上。
当执行查询时会根据查询类型做数据的重新分布或拷贝,因为有些join查询需要其他表的所有数据,这样一来肯定带来额外的I/O和网络负载,影响到整体的系统性能。这是也data redistribution
的目的:
可以使用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对查询的性能影响非常大。
解决redistribution的思路是使用KEY这种类型进行哈希分布,这样相同的值被分布到相同的slice,适合会进行join查询的列。
每个表只能有一个distribution key
,也就是说上面只能有一对fact table
和dimension table
能够在一起, 所以dimension table
要选最大的那个。PART
是最大的dimension table
。 PART
使用p_partkey
join LINEORDER
。 所以将 lo_partkey
当作LINEORDER
的distribution key
, p_partkey
当作 PART的distribution key
。当数据加载时,两个的中joining key会分布到同一个slice。
将其他dimension表使用ALL
distribution。
由于其他表没有机会和fact table分布到同一个slice,所以使用ALL类型分布,这样所有slice上都有dimension表的副本。使用ALL时会增加存储空间和和从S3加载到redshift的时间。
CUSTOMER, SUPPLIER, DWDATE
也会和LINEORDER
表进行join查询,所以这三个表全设置为DISTSTYLE ALL
。这三个表都非常小,而且不经常更新,对于加载时间和存储空间影响较小。
对其他表使用EVEN分布.
目前所有的表使用了KEY
或ALL
分布。所以不必再使用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自动压缩