我在CDH群集上有数据集,并且按yyyymm进行了分区。
当我在 hive 上运行以下查询时:
select actvydt, cast((concat(trim(substr(ActvyDt, 1, 4)), trim(substr(ActvyDt, 6, 2)))) as int) from pos where yyyymm=201601 and actvydt>='2016-01-01' and actvydt<='2016-01-09' limit 10;
它正在从数据集中达到201601的右分区。
结果如下:
actvydt yyyymm
2016-01-02 201601
2016-01-02 201601
2016-01-02 201601
但是,当我运行以下查询时:(只需通过subst和concat函数传递yyyymm的参数)
select actvydt,cast((concat(trim(substr(ActvyDt, 1, 4)), trim(substr(ActvyDt, 6, 2)))) as int) from pos.pos_sales_weekly where yyyymm=cast(trim((concat(trim(substr(ActvyDt, 1, 4)), trim(substr(ActvyDt, 6, 2))))) as int) and actvydt>='2016-01-01' and actvydt<='2016-01-09' limit 10;
它击中了整个数据集。因此,yyyymm的值未正确传递。此函数存在一些问题:
cast((concat(trim(substr(ActvyDt, 1, 4)), trim(substr(ActvyDt, 6, 2)))) as int)
但是函数的值作为列传递,可以在上面的结果中看到。它显示正确的参数201601。
任何帮助将是非常可贵的。
下面是表架构:
CREATE EXTERNAL TABLE IF NOT EXISTS pos (nid bigint, actvydt date, upc string, tchid string, posfileid string, yssk bigint) PARTITIONED BY (yyyymm int) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.avro.AvroSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat' LOCATION '/data/' TBLPROPERTIES ( 'avro.output.codec'='snappy' );
最佳答案
在执行查询之前,必须知道分区键值,才能进行分区修剪。您正在使用WHERE
子句:yyyymm=cast(trim((concat(trim(substr(ActvyDt, 1, 4)), trim(substr(ActvyDt, 6, 2))))) as int) and actvydt>='2016-01-01' and actvydt<='2016-01-09'
不幸的是,优化器没有智能,无法在执行查询之前从您相当复杂的函数中推断出yyyymm
值。尝试另外添加显式条件:yyyymm='201601'
这将起作用。您可以将其作为变量传递。