0%

Hive中日期存储格式的选用

Hive 提供了 DATE 类型作为存储日期的格式,但在大多数业务中还是用 STRING 格式来存储日期,那么为什么不使用 DATE 呢?


什么是DATE格式

HIve 中的 DATE 格式遵循 ISO 标准,用 YYYY-MM-DD 描述年月日。

测试用例

设计一些日期字符串用作测试用例,涵盖不同分隔符、简化的年月日,以及错误的日期等情景:

test_date.csv
1
2
3
4
5
6
7
8
9
10
11
12
2023-01-01
2023/01/02
20230103
2023-1-4
23-1-5
2023-1-06
2023-01-7
2023-02-31
2023-04-31
2023-05-31
2023-05-32
2023-13-01

在 Hive 中创建 test_date 表,载入文件数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
hive> create table test_date(dt date);
hive> load data local inpath '/data/file/test_date.csv' overwrite into table test_date;

hive> select date from test_date;
2023-01-01
NULL
NULL
2023-01-04
NULL
2023-01-06
2023-01-07
2023-03-03
2023-05-01
2023-05-31
NULL
NULL

将查询结果和原始数据放一起进行比较:

原始数据 查询结果
2023-01-01 2023-01-01
2023/01/02 NULL
20230103 NULL
2023-1-4 2023-01-04
23-1-5 NULL
2023-1-06 2023-01-06
2023-01-7 2023-01-07
2023-02-31 2023-03-03
2023-04-31 2023-05-01
2023-05-31 2023-05-31
2023-05-32 NULL
2023-13-01 NULL

可以看到 DATE 格式可以识别出来的日期字符串格式有以下特征:

  • 年、月、日之间使用 - 分割;
  • 年份必须完整;
  • 月和日支持短格式。

DATE 格式对日期也有一定的纠错能力:

  • 部分月份没有 29、30、31 日,会被纠正为下个月的相应日期,比如 4 月 31 日可以被自动纠正为 5 月 1 日;
  • 错误的日期数据,比如 13 月或 32 日会被记为 NULL

查询

使用文件内的原始字符串作为查询条件对表数据进行查询,用 IN 运算符指定这些字符串,看看能否查询出结果:

1
2
3
hive> select dt from test_date where dt in ('2023-01-01','2023/01/02','20230103','2023-1-4','23-1-5','2023-1-06','2023-01-7','2023-02-31','2023-04-31','2023-05-31','2023-05-32','2023-13-01');
2023-01-01
2023-05-31

似乎只有格式严格遵守 ISO 标准即 YYYY-MM-DD 且没被纠错过的字符串能得到查询结果。为了验证是否真的如此,把 IN 运算符中的字符串改为正确格式后再进行查询:

1
2
3
4
5
6
7
8
hive> select dt from test_date where dt in ('2023-01-01','2023-01-02','2023-01-03','2023-01-04','23-01-05','2023-01-06','2023-01-07','2023-03-03','2023-05-01','2023-05-31','2023-05-32','2023-13-01');
2023-01-01
2023-01-04
2023-01-06
2023-01-07
2023-03-03
2023-05-01
2023-05-31

修改后非 NULL 数据都能查询出来了。

难道只有对查询条件中的日期字符串做 ISO 标准化和纠错后才能查询到结果么?将 IN 运算符修改为 = 后再试下,发现用原始数据也可以查询到了:

1
2
3
4
5
6
7
8
hive> select dt from test_date where dt='2023-01-01' OR dt='2023/01/02' OR dt='20230103' OR dt='2023-1-4' OR dt='23-1-5' OR dt='2023-1-06' OR dt='2023-01-7' OR dt='2023-02-31' OR dt='2023-04-31' OR dt='2023-05-31' OR dt='2023-05-32' OR dt='2023-13-01';
2023-01-01
2023-01-04
2023-01-06
2023-01-07
2023-03-03
2023-05-01
2023-05-31

如何选择日期格式

问问 ChatGPT 的看法吧。

Hive 中存储日期使用 Date 好还是 String 好?

在使用 = 运算符时,查询条件中的日期字符串也支持短格式和纠错。

在Hive中存储日期数据,使用Date类型或者String类型都是可以的,具体应该根据实际情况来选择。下面是一些比较常见的考虑因素:

  • 存储空间:对于同一个日期,使用Date类型只需要占用4个字节的存储空间,而使用String类型可能会占用更多的存储空间。
  • 查询效率:如果需要对日期进行排序、分组等操作,使用Date类型通常比使用String类型更加高效。
  • 数据来源:如果日期数据源来自于文件或者数据库中的字符型字段,建议使用String类型,这样避免了类型转换带来的开销和错误。

总之,在选择日期类型时,需要考虑到具体的业务需求,权衡存储空间与查询效率等方面的利弊,并且需要注意保持数据的一致性,避免出现格式不统一、类型不匹配等问题。

为什么说 Hive 中 Date 类型比 String 类型对日期进行排序、分组等操作效率高?

在Hive中,Date类型比String类型对日期进行排序、分组等操作效率高的原因是因为Date类型本身是可以被序列化和反序列化的,而String类型则需要先进行解析。

具体来说,Date类型存储的是一个整数,而String类型存储的是一串字符。当Hive需要对其中一个字段进行排序或分组时,如果该字段是Date类型,则只需要将该整数进行比较即可;而如果该字段是String类型,则需要将每个字符串进行解析并转换为日期格式后再进行比较。这个过程会非常耗时和资源消耗。

此外,Date类型还有一个优势是它的排序和比较结果更加准确。由于String类型存储的是一串字符,因此可能存在诸如“2021-01-01”和“2021/01/01”这样的格式不同但实际表示同一日期的情况。而Date类型只存储日期值,不涉及任何格式问题,自然比较和排序更加准确和可靠。

因此,在Hive中,如果数据中包含日期信息,建议使用Date类型进行存储和处理,能够提高查询效率和准确性。