在一次数据仓库日常任务中,发现基于日期分区字段进行筛选的查询结果异常。查询特定分区的数据时,本该有数据的分区却返回空结果,但直接全表扫描又能看到数据。
具体表现为:查询dt='2023-06-01'
分区的数据返回空,但全表计数显示该分区确有数据。
-- 返回空结果
SELECT COUNT(*) FROM dwd.user_behavior WHERE dt='2023-06-01';
-- 却有数据
SELECT COUNT(*) FROM dwd.user_behavior;
首先确认数据是否真正入库:
-- 查看分区信息
SHOW PARTITIONS dwd.user_behavior;
结果显示确实存在dt=2023-06-01
分区
排查SQL语句写法是否正确,包括引号使用、字段名是否正确等
查看HDFS上该分区的数据文件是否存在:
hdfs dfs -ls /user/hive/warehouse/dwd.db/user_behavior/dt=2023-06-01
发现数据文件正常存在且大小不为空
使用DESCRIBE FORMATTED
命令查看表结构:
DESCRIBE FORMATTED dwd.user_behavior;
发现关键问题:分区字段dt
在表结构中定义为STRING类型,但通过SHOW CREATE TABLE
查看建表语句时发现,实际的分区字段值存储为字符串,但查询时使用了日期格式的字符串。
进一步检查发现,有些分区的值为20230601
(字符串),有些为2023-06-01
(也是字符串),导致按特定格式查询时匹配失败。
问题根源在于数据入库时分区字段值格式不统一:
yyyyMMdd
格式yyyy-MM-dd
格式首先修复现有数据的分区格式:
-- 1. 创建临时表备份数据
CREATE TABLE dwd.tmp_user_behavior LIKE dwd.user_behavior;
-- 2. 将原表数据插入临时表,统一分区格式
INSERT OVERWRITE TABLE dwd.tmp_user_behavior PARTITION(dt)
SELECT
field1,
field2,
-- 其他字段...
CASE
WHEN LENGTH(dt) = 8 THEN CONCAT(SUBSTR(dt,1,4),'-',SUBSTR(dt,5,2),'-',SUBSTR(dt,7,2))
ELSE dt
END as dt
FROM dwd.user_behavior;
-- 3. 删除原表数据
TRUNCATE TABLE dwd.user_behavior;
-- 4. 将数据插回原表
INSERT OVERWRITE TABLE dwd.user_behavior PARTITION(dt)
SELECT * FROM dwd.tmp_user_behavior;
-- 5. 清理临时表
DROP TABLE dwd.tmp_user_behavior;
修改查询语句,兼容两种格式:
-- 修改查询条件,兼容两种格式
SELECT COUNT(*) FROM dwd.user_behavior
WHERE dt IN ('2023-06-01', '20230601');
-- 示例检查语句
SELECT DISTINCT dt, LENGTH(dt) as length
FROM dwd.user_behavior
WHERE dt IS NOT NULL;
-- 推荐方式
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
INSERT OVERWRITE TABLE dwd.user_behavior PARTITION(dt)
SELECT
field1,
field2,
-- 使用统一函数生成分区值
FROM_UNIXTIME(UNIX_TIMESTAMP(event_time), 'yyyy-MM-dd') as dt
FROM source_table;
这次经历让我深刻认识到,即使是简单的字符串类型分区字段,格式不统一也会导致严重的数据查询问题。在大数据开发中,数据质量的控制需要从细节做起,规范先行才能避免后续的排查成本。
为避免类似问题再次发生,我们团队制定了以下规范:
通过这些措施,我们成功避免了类似问题的再次发生,提高了数据仓库的稳定性和可靠性。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。