Hive - Parquet 格式 - OR 子句在未按预期工作的地方
Posted
技术标签:
【中文标题】Hive - Parquet 格式 - OR 子句在未按预期工作的地方【英文标题】:Hive - Parquet format - OR clause in where not working as expected 【发布时间】:2018-11-22 18:38:17 【问题描述】:我正在创建一个表格并插入如下数据
CREATE TABLE `mydb.mytable`(
`seq_num` decimal(18,0),
`ins_upd_flag` char(1)
)
stored as parquet;
INSERT OVERWRITE TABLE mydb.mytable
SELECT 10457 SEQ_NUM,'I' INS_UPD_FLAG UNION ALL
SELECT 10462,'I' UNION ALL
SELECT 10461,'I' UNION ALL
SELECT 10460,'I' UNION ALL
SELECT 10459,'I' UNION ALL
SELECT 10456,'I' UNION ALL
SELECT 10458,'I';
正如您在上面看到的,第二列的值只是“I”,它没有任何多余的字符。
当我运行以下查询时,它不会产生任何结果
SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG))
FROM mydb.mytable T
WHERE SEQ_NUM <> 0 OR INS_UPD_FLAG <> 'I' ;
但是,如果我运行以下查询,它会按预期返回所有插入的行
SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG)) -- both length =1
FROM mydb.mytable T
WHERE SEQ_NUM <> 0 OR TRIM(INS_UPD_FLAG) <> 'I' ;
关于为什么会发生这种情况以及如何解决的任何解释?我需要不使用修剪的结果
请注意,此问题仅在 OR 条件下发生。如果我运行以下查询,我会得到结果
SELECT T.*, length(INS_UPD_FLAG), length(trim(INS_UPD_FLAG))
FROM mydb.mytable T
WHERE SEQ_NUM <> 0 and INS_UPD_FLAG = 'I' ;
另外,如果我使用 ORC 或文本格式创建表格,我会得到没有修剪的结果。
【问题讨论】:
【参考方案1】:我设法重新解决了您的问题并获得了与您解释的相同的结果。
我运行了一个查询以查看您的 where 条件究竟产生了什么:
SELECT
T.*,
length(INS_UPD_FLAG),
length(trim(INS_UPD_FLAG)),
SEQ_NUM <> 0,
INS_UPD_FLAG = 'I',
SEQ_NUM <> 0 or INS_UPD_FLAG = 'I'
FROM mydb.mytable T
结果如下:
|seq_num|ins_upd_flag|_c1|_c2|_c3 |_c4 |_c5 |
|10457 |I |1 |1 |true|true|true|
|10462 |I |1 |1 |true|true|true|
|10461 |I |1 |1 |true|true|true|
|10460 |I |1 |1 |true|true|true|
|10459 |I |1 |1 |true|true|true|
|10456 |I |1 |1 |true|true|true|
|10458 |I |1 |1 |true|true|true|
如您所见,它为您的加入条件返回 true
。
出于好奇,我将 where 条件包裹在 ()
周围并得到了没有修剪的结果。
SELECT
T.*,
length(INS_UPD_FLAG),
length(trim(INS_UPD_FLAG)),
SEQ_NUM <> 0,
INS_UPD_FLAG = 'I',
SEQ_NUM <> 0 or INS_UPD_FLAG = 'I'
FROM mydb.mytable T
where (SEQ_NUM <> 0 or INS_UPD_FLAG = 'I')
结果:与上一个查询相同。
我通过 Hue 2.6.1-227 使用 Hive 1.2.1000。
我不知道 ()
在做什么魔术以及为什么没有它查询就无法工作。
【讨论】:
很好的发现。不幸的是,括号“()”在我的配置单元版本中没有任何作用(HDP 上的配置单元 1.2.1000.2.6.5.0-292)。这看起来像 Hive 1.2 的错误【参考方案2】:我可以知道您为什么不想使用修剪功能的原因。由于 hadoop 将数据存储在文件中,因此它很有可能在插入时添加空间。我在使用 parque 格式时经常遇到这个问题.这取决于有时你会面对它,有时你不会面对它。 无论是什么,您都可以仅根据此条件运行查询 选择 T.*,长度(INS_UPD_FLAG),长度(修剪(INS_UPD_FLAG)) FROM mydb.mytable T WHERE SEQ_NUM 0
if it is not returning anything the way data inserted is wrong..please try it let me know
【讨论】:
我不想使用 trim,因为我有一个与分区列类似的 char 列,并且我不确定是否将使用 trim(partitioned_column) 的条件用于谓词下推 *我不确定 trim(partitioned_column) 是否会用于分区扫描【参考方案3】:首先,我不确定您为什么没有看到预期的结果。我在下面进行了非常相似的测试,并收到了预期的结果。你在哪个版本的 Hive 上?我在 hive-1.1.0+cdh5.13.3+1307 (Cloudera distro w/v5.13) 上做了同样的测试:
CREATE TABLE test_cond_parq
(
seq_num decimal(10,0),
ind string
)
STORED AS PARQUET;
INSERT INTO TABLE test_cond_parq
SELECT 10457, 'I' UNION ALL
SELECT 10458, 'I'
;
然后我运行了以下查询,类似于您上面的查询...
SELECT *, LENGTH(ind) len_ind, LENGTH(TRIM(ind)) len_trim_ind
FROM test_cond_parq
WHERE seq_num <> 0 OR ind <> 'I';
这返回了以下结果:
10457 | I | 1 | 1
10458 | I | 1 | 1
【讨论】:
我正在使用 Hive 1.2.1000.2.6.5.0-292 感谢您试用。我很惊讶为什么它在我使用的版本中不起作用。 NP。您在哪个 SQL 编辑器中运行测试?我是在 HUE 中做的,所以可能与此有关?以上是关于Hive - Parquet 格式 - OR 子句在未按预期工作的地方的主要内容,如果未能解决你的问题,请参考以下文章
测试ClickHouse中写入Parquet格式数据到Hive
hudi使用cow生成parquet格式用hive查询的问题
使用 Java 将 Json 对象转换为 Parquet 格式而不转换为 AVRO(不使用 Spark、Hive、Pig、Impala)