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 子句在未按预期工作的地方的主要内容,如果未能解决你的问题,请参考以下文章

Hive中Parquet格式的使用

测试ClickHouse中写入Parquet格式数据到Hive

hudi使用cow生成parquet格式用hive查询的问题

hive最早在哪个版本起支持Parquet格式

hive 插入parquet二级分区表数据倾斜优化

使用 Java 将 Json 对象转换为 Parquet 格式而不转换为 AVRO(不使用 Spark、Hive、Pig、Impala)