官方文档
https://docs.aws.amazon.com/zh_cn/redshift/latest/dg/t_Sorting_data.html
https://docs.aws.amazon.com/zh_cn/redshift/latest/dg/t_Distributing_data.html
个人理解:
SORTKEY排序键:就是类似传统关系型数据库的索引,而复合排序键就对应传统关系型数据库的复合索引,用复合索引时要按前导列的规则使用
DISTKEY分配键:就是如何把整表的数据如何分散存放到各个节点,表的分配方式将表中的行分配到各个计算节点这样就可以将工作负载均匀地分配到集群中的节点上,分配方式有四种AUTO、EVEN、KEY 或 ALL,其中KEY表示根据表的特定列中的值分配行,不同的分配方式会导致相同的表的大小不一样,比如一张表在KEY分配方式下可能1GB,在EVEN分配方式下可能10GB,在20节点下ALL分配方式下可能20GB(因为ALL方式是向每个节点分配整个表的副本)
SORTKEY排序键
创建表时,您也可以将其一个或多个列定义为SORTKEY排序键。初次向空表中加载数据时,行以排序顺序存储在磁盘上。有关排序键列的信息会被传递给查询计划程序,后者借助该信息构建能够充分利用数据排序方式的计划。排序可实现范围限制谓词的高效处理。Amazon Redshift 将列式数据存储在 1 MB 的磁盘数据块中。每个数据块的最小值和最大值作为元数据的一部分存储。如果查询使用范围限制谓词,则查询处理器可在表扫描期间借助该最小值和最大值快速跳过大量的数据块。例如,假设某张表存储着按日期排序的五年数据,且查询指定了一个月的日期范围。在这种情况下,您可以从扫描中消除多达 98% 的磁盘块。如果数据未排序,则该查询就不得不扫描更多(也可能是全部)的磁盘数据块。
备注:分布键和排序键是定义数据物理存储方式的表属性。分配和排序键使用不正确通常会导致DISK FULL磁盘空间已满的错误
要定义排序类型,请在您的 CREATE TABLE 或 CREATE TABLE AS 语句中使用 INTERLEAVED 或 COMPOUND 关键字。默认为 COMPOUND。建议使用默认的 COMPOUND,除非您的表没有使用 INSERT、UPDATE 或 DELETE 定期更新。
复合排序键:复合键由排序键定义中列出的所有列组成(顺序即为其排列顺序)。当查询的筛选条件应用了使用排序键前缀的条件(如筛选条件和联接)时,复合排序键最为有用。当查询只依赖于辅助排序列而不引用主列时,复合排序的性能优势会下降。COMPOUND 是默认的排序类型。
交错排序键:交错排序为排序键中的每个列或列的子集赋予相同的权重。如果多个查询使用不同的列作为筛选条件,则通常可以使用交错排序方式来提高这些查询的性能。当查询对辅助排序列使用限制性谓词时,与复合排序相比,交错排序可显著提高查询的性能。不要在具有单调递增属性的列(例如,身份列、日期或时间戳)上使用交错排序键。交错排序的优势随着受限制排序列数量的增加而增大。交错排序对于大型表更为有效。在您向已包含数据的排序表中不断添加行的过程中,性能会逐渐下降。复合排序和交错排序都会出现这种性能下降,但交错表受到的影响更大。VACUUM 可恢复排序顺序,但对于交错表,该操作可能需要花费更长的时间,因为合并新的交错数据可能涉及到修改每一个数据块。
DISTKEY分配键
创建表时,您可以指定四种分配方式之一:AUTO、EVEN、KEY 或 ALL。如果未指定分配方式,Amazon Redshift 使用自动 (AUTO) 分配。
AUTO 分配:在自动 (AUTO) 分配方式下,Amazon Redshift 基于表数据大小分配最佳分配方式。例如,如果指定 AUTO 分配方式,Amazon Redshift 最初向小型表指定的是 ALL 分配方式。当表变大时,Amazon Redshift 可能会将分配方式更改为 KEY,选择主键(或复合主键的列)作为分配键。如果表变大且没有任何一列适合用作分配键,Amazon Redshift 会将分配方式更改为 EVEN。分配方式的更改在后台进行,对用户查询的影响极小。
EVEN 分配:不管任意特定列中的值是什么,领导节点都以轮询方式向所有切片分配行。当表不参与联接时,适合使用 EVEN 分配。
KEY 分配:根据一列中的值分配行。领导节点会将匹配的值放置到同一个节点切片上。如果基于联接键分配一对表,领导节点会根据联接列中的值在切片上并置行。这样一来,共同列的匹配值将实际存储在一起。
ALL 分配:向每个节点分配整个表的副本。EVEN 分配或 KEY 分配只将表中的部分行放置在每个节点上,ALL 分配需要以集群中节点数量为倍数的存储空间,因此,它需要长得多的时间来加载、更新或插入数据到多个表中。ALL 分配只适用于移动相对缓慢的表;即更新不频繁、不广泛的表。由于在查询过程中重新分配小表的成本很低,因此将小维度表定义为 DISTSTYLE ALL 没有显著好处。
Amazon Redshift 集群是一组节点。集群中的每个节点拥有自己的操作系统、专用内存和专用磁盘存储。一个节点是领导节点,它负责将数据和查询处理任务分配到计算节点。计算节点的磁盘存储分成一系列切片。每个节点的切片数取决于集群的节点大小。例如,每个 DS2.XL 计算节点有两个切片,每个 DS2.8XL 计算节点有 16 个切片。所有节点均参与并行查询的运行,处理尽可能跨切片均匀分布的数据。
将数据加载到表中时,Amazon Redshift 会根据表的分配方式将表中的行分配到各个节点切片。作为查询计划的一部分,优化程序确定需要将数据块放置在何处,以最好地运行查询。然后,在查询运行时,查询优化程序根据执行任何联接和聚合的需要将行重新分配到计算节点。重新分配可能涉及将特定的行发送到节点以进行联接,或将整个表广播到所有节点。选择表分配方式的目的是通过在执行查询前将数据放在需要的位置来最大程度地减小重新分配步骤的影响。数据分配有两个主要目标:
1、将工作负载均匀地分配到集群中的节点上。不均匀的分配或数据分配偏斜会导致某些节点执行的工作比其他节点多,从而影响查询性能。
2、尽量减少查询运行时的数据移动。如果参与联接或聚合的行已在节点上与其在其他表中联接行并置,则优化程序在查询运行时不必重新分配过多的数据。
SALES表,LISTID为分配键,LISTID 和 SELLERID为多列复合排序键。
create table sales(
salesid integer not null,
listid integer not null,
sellerid integer not null,
buyerid integer not null,
eventid integer not null encode mostly16,
dateid smallint not null,
qtysold smallint not null encode mostly8,
pricepaid decimal(8,2) encode delta32k,
commission decimal(8,2) encode delta32k,
saletime timestamp,
primary key(salesid))
distkey(listid)
COMPOUND sortkey(listid,sellerid)
查询某个schema下的哪些表有排序键或分配键
select "schema","table",diststyle,sortkey1,sortkey_num,tbl_rows,skew_sortkey1,skew_rows from SVV_TABLE_INFO where schema='SS' order by "table"
查询某表的哪些列是排序键或分配键,如果是复合排序键则排序键中的所有列将具有一个正值且该值指示列在排序键中的位置。如果是交错排序键,则排序键中的所有列将具有一个正值或负值且该值的绝对值指示列在排序键中的位置。
select schema_name,table_name,column_name,ordinal_position,data_type,distkey,sortkey from SVV_REDSHIFT_COLUMNS where schema_name='SS'
and table_name='TT1' and (distkey='true' or sortkey<>0)
创建一张表,指定了sortkey和distkey,怎么判断查询语句使用到了sortkey?
在查询语句前面加一个explain就可以得到redshift根据metadata生成的query plan。
曾经遇到的问题,下面sql语句很慢,怎么让它快一点?
update tf.all_china_stock_daily set non_linear_fct4 = b.cov_XY from #TF_alpha_1_final1 as b
where tf.all_china_stock_daily.tradedate = b.tradedate and tf.all_china_stock_daily.osid = b.osid;
分析和处理思路:all_china_stock_daily表的osid、tradedate字段是sort key,而语句中where条件前面是tradedate后面是osid,顺序和sort key相反,所以把语句调整,where条件后面先用osid再用tradedate,sql语句就变快了