Hologres从V2.0版本开始支持Runtime Filter,在多表Join场景下自动优化Join过程的过滤行为,提升Join的查询性能。本文为您介绍在Hologres中Runtime Filter的使用。
背景信息
应用场景
Hologres从 V2.0版本开始支持Runtime Filter,通常应用在多表(2表及以上)Join,尤其是大表Join小表的场景中,无需手动设置,优化器和执行引擎会在查询时自动优化Join过程的过滤行为,从而降低IO开销,以此提升Join的查询性能。
原理介绍
在了解Runtime Filter原理之前,需先了解Join过程。两个表Join的SQL示例如下:
select * from test1 join test2 on test1.x = test2.x;
其对应的执行计划如下。
如上执行计划,两个表Join时,会通过test2
表构建Hash表,然后匹配test1
表的数据,最后返回结果。在这个过程中,Join时会涉及到两个名词:
build端:两表(或者子查询)做Hash Join时,其中一张表(子查询)的数据会构建成Hash表,这一部分称为build端,对应计划里的Hash节点。
probe端:Hash Join的另一边,主要是读取数据然后和build端的Hash表进行匹配,这一部分称为probe端。
通常来说,在执行计划正确的情况下,小表是build端,大表是probe端。
Runtime Filter的原理就是在HashJoin过程中,利用build端的数据分布,生成一个轻量的过滤器(filter),发送给probe端,对probe端的数据进行裁剪,从而减少probe端真正参与Join以及网络传输的数据量,以此来提升Join性能。
因此Runtime Filter更适用于大小表Join,且表数据量相差较大的场景,性能将会比普通Join有更多的提升。
使用限制和触发条件
使用限制
仅Hologres V2.0及以上版本支持Runtime Filter。
仅支持Join条件中只有一个字段,如果有多个字段将不会触发Runtime Filter。从Hologres V2.1版本开始,Runtime Filter支持多个字段Join,如果多个Join字段满足触发条件,也会触发Runtime Filter。
触发条件
Hologres本身支持高性能的Join,因此Runtime Filter会根据查询条件在底层自动触发,但是需要SQL满足下述所有条件才能触发:
probe端的数据量在100000行及以上。
扫描的数据量比例:
build端 / probe端 <= 0.1
(比例越小,越容易触发Runtime Filter)。Join出的数据量比例:
build端 / probe端 <= 0.1
(比例越小,越容易触发Runtime Filter)。
Runtime Filter示例
如下示例帮助您更好理解Runtime Filter。
示例1:Join条件中只有1列。
begin; create table test1(x int, y int); call set_table_property('test1', 'distribution_key', 'x'); create table test2(x int, y int); call set_table_property('test2', 'distribution_key', 'x'); end; insert into test1 select t, t from generate_series(1, 100000) t; insert into test2 select t, t from generate_series(1, 1000) t; analyze test1; analyze test2; explain select * from test1 join test2 on test1.x = test2.x;
执行计划如下:
如上执行计划,
test2
表只有1000行,test1
表有100000行,build端和probe端的数据量比例是0.01小于0.1,且Join出来的数据量build端和probe端比例是0.01低于0.1,满足Runtime Filter的默认触发条件,因此引擎会自动使用Runtime Filter。同时在执行计划中,也可以看到probe端的test1
表有Runtime Filter Target Expr
节点,表示probe端使用了Runtime Filter下推。示例2:Join条件中有多列(Hologres V2.1版本支持)。
create table t1(id1 int not null, id2 int not null); create table t2(id1 int not null, id2 int not null); -- 建表,t1数据量较小,作为构建端可以broadcast insert into t1 select t, t+100 from generate_series(1, 10000) t; insert into t2 select t/10, t/10+100 from generate_series(1, 10000000) t; --更新执行计划 analyze t1, t2; -- 验证多列runtime filter explain select * from t1 join t2 on t1.id1=t2.id1 and t1.id2=t2.id2;
执行计划如下:
- 本页导读 (1)