Distribution key介绍
在Hologres中,Distribution Key属性指定了表数据的分布策略,系统会保证Distribution Key相同的记录被分配到同一个Shard上。
Distribution Key是非常重要的分布式概念,合理设置Distribution Key可以达到如下效果:显著提高计算性能。
不同的Shard可以进行并行计算,从而提高计算性能。显著提高每秒查询率(QPS)。
当您以Distribution Key做过滤条件时,Hologres可以直接筛选出数据相关的Shard进行扫描。否则Hologres需要让所有的Shard参与计算,影响QPS。显著提高Join性能。
当两张表在同一个Table Group内,并且Join的字段是Distribution Key时,那么数据分布保证表A一个Shard内的数据和表B同一Shard内的数据对应,只需要直接在本节点Join本节点数据(Local Join)即可,可以显著提高执行效率。
使用建议
Distribution Key设置原则总结如下:
Distribution Key尽量选择分布均匀的字段,否则容易因为数据倾斜导致负载倾斜,使得查询效率变低。
选择Group By频繁的字段作为Distribution Key**。
Join场景中,设置Join字段为Distribution Key,实现Local Join,避免数据Shuffle。同时进行Join的表需要在同一个Table Group内。
不建议为一个表设置多个Distribution Key,建议设置的Distribution Key不超过两个字段。设置多字段为Distribution Key,查询时若没有全部命中,容易出现数据Shuffle。
为表设置了Distribution Key之后,数据会根据Distribution Key被分配到各个Shard上,算法为Hash(distribution_key)%shard_count,结果为对应的Shard。系统会保证Distribution Key相同的记录会被分配到同一个Shard上,
不设置Distribution Key时,数据将会被随机分布在各个Shard,相同的数据可能会在相同Shard,也可能在不同的Shard
Group By聚合场景设置Distribution Key
为表设置了Distribution Key,那么相同的数据就分布在相同的Shard上,同时对于Group By聚合场景,数据在计算时按照设置的Distribution Key重新分布,因此可以将Group By频繁的字段设置为Distribution Key,这样数据在Shard内就已经聚合,减少数据在Shard间的重分配,提高查询性能,
设置Distribution Key需要在建表时设置,建表后如需修改Distribution Key需要重新建表并导入数据。
支持单列或者多列设置为Distribution Key,指定列时如设置单列,命令语句中不要保留多余空格;如设置多个列,则以半角逗号(,)分隔,同样不要保留多余空格。指定多列为Distribution Key时,列的顺序不影响数据的布局和查询性能。
不支持将Float、Double、Numeric、Array、Json及其他复杂数据类型的字段设为Distribution Key。
表设置了主键(PK)时,Distribution Key必须为PK或者PK中的部分字段(不能为空,即不指定任何列),因为要求同一记录的数据只能属于一个Shard。如果没有额外指定Distribution Key,默认将PK设置为Distribution Key。
技术原理:
为表设置了Distribution Key之后,数据会根据Distribution Key被分配到各个Shard上,算法为Hash(distribution_key)%shard_count,结果为对应的Shard。系统会保证Distribution Key相同的记录会被分配到同一个Shard上。
Local Join
Hologres数据库中的"Local Join"是一种优化查询性能的技术,它允许在执行查询时将两张表中的数据在本地进行连接操作,而不是在分布式环境下进行。这种操作主要适用于那些数据量不大,可以完全加载到内存中的情况。
在Hologres数据库中,“Local Join"是指在执行SQL查询时,当遇到需要连接操作的查询,Hologres会尝试将连接的表加载到执行查询的机器的内存中,然后在内存中执行连接操作。这种操作方式的优势在于避免了分布式环境下进行连接操作的开销,提高了查询性能。
假设我们有两个表,表A和表B,它们需要根据某个相同的键进行连接操作。在没有使用"Local Join"的情况下,Hologres需要在分布式环境下执行连接操作,这可能会带来一些开销。但是,如果我们启用了"Local Join”,Hologres会尝试将这两个表中的数据加载到执行查询的机器的内存中,然后在内存中执行连接操作。这样就可以避免分布式环境下进行连接操作的开销,提高了查询性能。
需要注意的是,"Local Join"有一定的限制,因为这种方式只适用于那些数据量不大,可以完全加载到内存中的情况。如果数据量过大,超出内存容量,那么这种方式就无法使用。因此,在使用"Local Join"时需要根据实际情况进行评估和选择。
在查询中指定"Local Join"选项。可以使用以下语法来指定"Local Join"选项:
SELECT * FROM table1 LOCAL JOIN table2 ON table1.id = table2.id;
在上面的示例中,table1和table2是要连接的两个表,id是连接条件。通过在查询中使用LOCAL JOIN关键字,可以启用"Local Join"。
4. 执行查询并观察查询结果。Hologres将尝试将涉及的表加载到内存中,并在内存中执行连接操作。如果成功启用了"Local Join",查询性能将得到提高,并且查询结果将返回更快的速度。
需要注意的是,启用"Local Join"后,如果涉及的表的大小超过了可用内存容量,将会导致查询失败或出现错误。因此,在使用"Local Join"时,建议先评估表的大小和可用内存容量,以确保查询能够成功执行并返回正确的结果。
查看执行计划
EXPLAIN ANALYZE
开启查看更详细执行计划
set hg_experimental_show_execution_statistics_in_explain = on;
EXPLAIN ANALYZE
两表Join字段未都设置为Distribution Key