天天看点

使用EMR 批处理的最佳实践-谓词下推

批计算中的多元索引查询方式可以自定义谓词下推配置。目前只能设置与Long、String类型的列做大小比较的谓词是否下推。

背景信息

谓词下推适用于当多元索引中多字段过滤的中间结果数据量较大,则中间结果的合并较为耗时的场景。此时可以将某些字段的过滤从存储层(表格存储)提到计算层(Spark)处理,提高查询效率。

例如

select * from table where a = 10 and b < 999999999;

,如果a = 10返回的结果只有1000条,b < 999999999返回的结果有一亿条,则在存储层将1000条结果与一亿条结果做合并比较耗时,此时把b < 999999999提到计算层,Spark只需要对存储层返回的1000条数据作过滤,大大降低了存储层的压力。

谓词支持

Spark谓词支持情况请参见下表。

Spark 是否支持 SQL举例
And select * from table where a > 1 and b < 0 
Or select * from table where a > 1 or b < 0
Not select * from table where a != 1
EqualTo select * from table where a = 1
Not+EqualTo select * from table where a != 1
IsNull select * from table where a is null table表中没有a列的行
In select * from table where a in {1,2,3} 默认最大限制1024
LessThan select * from table where a < 10 如果SQL语句中使用该谓词的列的类型为Long或者String,则可以通过谓词下推配置设置是否下推,详情见下一节"谓词下推支持说明"
LessThanOrEqual select * from table where a <=10 如果SQL语句中使用该谓词的列的类型为Long或者String,则可以通过谓词下推配置设置是否下推,详情见下一节"谓词下推支持说明"
GreaterThan select * from table where a > 10 如果SQL语句中使用该谓词的列的类型为Long或者String,则可以通过谓词下推配置设置是否下推,详情见下一节"谓词下推支持说明"
GreaterThanOrEqual select * from table where a >= 10 如果SQL语句中使用该谓词的列的类型为Long或者String,则可以通过谓词下推配置设置是否下推,详情见下一节"谓词下推支持说明"
StringStartsWith select * from table where a like "tablestore%" table表中a列以tablestore为prefix的行全部返回
地理坐标(String Json)中心距离 select * from table where val_geo = '{"centerPoint":"3,0", "distanceInMeter": 100000}' 圆心半径决定的地理圆圈
地理坐标(String Json)矩形框 select * from table where geo = '{"topLeft":"8,0", "bottomRight": "0,10"}' 左上角,右下角决定的地理矩形
地理坐标(String Json)多边形框 select * from table where geo = '{"points":["5,0", "5,1", "6,1", "6,10"]}' 多个点组成的地理多边形

谓词下推配置

谓词下推配置的参数需要在创建Spark外表时配置。谓词下推规则如下:

  • 当过滤条件中的逻辑谓词只存在AND和NOT时,可以自定义谓词是否下推。
  • 当过滤条件中的逻辑谓词存在OR时,谓词全部下推,自定义的谓词下推配置(例如E-MapReduce SQL方式的参数配置push.down.range.long=false和push.down.range.string=false)不会生效。

不同的逻辑谓词和下推配置组合使用时,SQL语句举例及预期效果请参见下表。

逻辑谓词 下推配置 预期效果
全为AND push.down.range.long=true push.down.range.string=true select * from table where val_long1 > 1000 and val_long1 is null and name like 'table%' and pk in {12341,213432} SQL正常
push.down.range.long=false select * from table where val_long1 > 1 and name like 'table%' 与Long类型做大小比较的谓词(LessThan LessThanOrEqual GreaterThan GreaterThanOrEqual)都不会被下推,该谓词交由Spark层来做过滤 spark层获取到的是name like 'table%'的数据,val_long1 > 1交由spark过滤
push.down.range.string=false select * from table where val_string1 > 'string1' and name like 'table%' 与String类型做大小比较的谓词(LessThan LessThanOrEqual GreaterThan GreaterThanOrEqual)都不会被下推,该谓词交由Spark层来做过滤 spark层获取到的是name like 'table%'的数据,val_string1 > 'string1'交由spark过滤
存在地理列 select * from table where val_geo = '{"centerPoint":"3,0", "distanceInMeter": 100000}' and val_long1 = 37691900 and val_long2 > 2134234 SQL正常val_long2 > 2134234能否被过滤则取决于push.down.range.long的配置
存在OR long,string都配置为可以下推push.down.range.long=true push.down.range.string=true select * from table where val_long1 > 1000 or val_long1 is null or name like 'table%' and pk in {12341,213432}
select * from table where val_geo = '{"centerPoint":"3,0", "distanceInMeter": 100000}' or val_long1 = 37691900
push.down.range.long=false 且SQL语句中存在rangeLong 的过滤字段 此时push.down.range.long=false不生效,SQL谓词全部下推
push.down.range.string=false 且SQL语句中存在rangeString 的过滤字段 此时push.down.range.string=false不生效,SQL谓词全部下推