1、问题

如何删除Hive分区名有特殊字符的分区?

2、背景

最近在做数据治理工作,在Hive的元数据库里瞎逛的时候发现了一个奇怪的分区 dt=%7Bdt} ,发现几个问题:

  1. hdfs有数据,但是无法使用SQL的where条件查询分区数据,使用转义也失效
  2. 无法使用 analyze table 统计分区信息
  3. count 全表会计算数据,但是又无法过滤查询,可能对数据统计造成影响

考虑到分区无法使用,还可能对数据统计造成干扰,于是想要对分区进行删除。然后问题来了,使用了

  1. ALTER TABLE db_name.table_name drop partition (dt='%7Bdt}')

无法删除

3、解决方案

3.1、 我们取正常的一天数据和有问题的分区名进行比较

正常 问题
dt=20190429 dt=%7Bdt}

发现还是有一定的规律,正常情况下的日期字段居然变成了 %7Bdt} ,看起来像是没有赋值的 {dt}
字符 { 变成了 %7B ,经过查找确认,%7B{ 的URL编码

3.2、 网上冲浪找解决办法

在网上找到一篇类似的文章[1]

hive sql脚本中带变量如:select table_coulm from table_name where dt=’{etl_date}’; —dt是分区名 如果变量未赋值,{etl_date}会变成特殊字符dt=$%7Betl_date} 删除带特殊字符的分区:alter table tmp_h02_click_log drop partition(dt=’${etl_date}’); 直接删除原有的变量名不要带转义字符。 hive 处理字段是忘记起别名 hive会默认生成一个列名如:_c1 查询_c1 必须用反向引号括起来 _c1

按照博主的意思,是没有对变量赋值, {dt} 以某种不可知(未读源码)的方式变成了 %7Bdt}

3.3、 尝试使用以下删除语句对分区进行阐述

  1. ALTER TABLE db_name.table_name drop partition(dt='{dt}');

终端输出如下

  1. ls: cannot access /usr/local/xyhadoop/spark/lib/spark-assembly-*.jar: No such file or directory
  2. Logging initialized using configuration in file:/usr/local/xyhadoop/apache-hive-1.2.2-bin/conf/hive-log4j.properties
  3. Dropped the partition dt=%7Bdt}
  4. OK
  5. Time taken: 2.371 seconds

从打印出来的日志里观察可以发现,确实是 {dt} 变成了 %7Bdt} ,我们用 {dt} 作为分区名称仍然可以成功删除。检查数据库,分区成功删除,该方法确实有效。

3.4、复现验证

我尝试使用下面的SQL进行插入数据,能复现博客中作者说的情况。

  1. insert overwrite table db_name.table_name partition(dt='{dt}')

然后使用下面SQL进行删除数据

  1. ALTER TABLE db_name.table_name drop partition(dt='{dt}');

3.5、其他解决方案

在网上找解决问题的方案时,很多人都是直接删除HDFS文件,之后再删除hive元数据。如https://blog.csdn.net/fg654748861/article/details/46123887这篇文章所示。

尽管这能很简单的解决问题,但是不是很建议这样用,原因有以下几点

  • 1、元数据库的del权限很高且危险,一般情况下开发人员不应该有该权限
  • 2、需要依次删除所有相关的 PARTITIONSPARTITION_PARAMS 等数据表里的相关数据

总的来说操作风险较高

4、总结

  • 使用 ALTER TABLE db_name.table_name drop partition(dt='{dt}') 能删除分区
  • %7B{ 的URL编码表
  • 其他的字符有可能出现在Hive元数据中,如果分区名称是%23dt%23,原字符是 #dt## 的 URL编码是%23
  • 猜想可能是SQL执行过程中经过了一次HTTP传输,将为负值的特殊符号转成了URL编码

5、参考

[1] forever_ai.hive删除分区名带特殊字符.CSDN:博客,2014-03-03
[2] 百度.URL编码表.百度百科:词条