当前位置:   article > 正文

上亿条数据,如何比对并发现两个表数据差异_hive 两张表全量数据对比

hive 两张表全量数据对比

目录

一、背景

二、分析流程

三、验数方法

3.1 数据量级比对

3.2 一致性比对

3.2.1 勾稽验证+md5方法

3.2.2 暴力比对法

3.3 差异数据发现

四、总结

本文是考拉验数(自动化验数)设计方案和实现中核心的验数SQL。

一、背景

做数据,经常遇到数据验证,很烦很枯燥,即耗时又耗人,但又必须去做。如何去做数据验证,并标准化整个流程,让验数变得轻松。

二、分析流程

……

相同表结构数据验证:比如修改表逻辑

相似表结构数据验证:比如修改表字段。

新表数据校验:比如新开发了表,选择一个比对表参考等等

三、验数方法

数据验证三步走:

  1. 数据量级比对:先比对两个表核心字段数据量级,如果量级不同,两个表数据肯定不一致。
  2. 一致性比对:如果量级相同,比对一致性。
  3. 差异数据发现:如果数据不一致,把不一致的数据打印出来。

3.1 数据量级比对

  1. select left_table.pv-right_table.pv as pv_diff,
  2. left_table.user_id_uv - right_table.user_id_uv as user_id_uv_diff,
  3. left_table.order_id_uv - right_table.order_id_uv as order_id_uv_diff,
  4. left_table.city_id_uv - right_table.city_id_uv as city_id_uv_diff
  5. from (
  6. select count(1) as pv,
  7. count(distinct user_id) as user_id_uv,
  8. count(distinct order_id) as order_id_uv,
  9. count(distinct city_id) as city_id_uv
  10. from mart_online.fact_user_order_day
  11. where dt=20190413
  12. )left_table
  13. left outer join (
  14. select count(1) as pv,
  15. count(distinct user_id) as user_id_uv,
  16. count(distinct order_id) as order_id_uv,
  17. count(distinct city_id) as city_id_uv
  18. from mart_test.fact_user_order_day
  19. where dt=20190413
  20. )right_table
  21. on 1=1
  1. 左表pv减去右表pv值为:[0],核心字段uv差为:[0] 即两个表数据条数相同
  2. +-------+----------------+------------------+---------------+
  3. |pv_diff|user_id_uv_diff |order_id_uv_diff |city_id_uv_diff|
  4. +-------+----------------+------------------+---------------+
  5. | 0| 0| 0| 0|
  6. +-------+----------------+------------------+---------------+

3.2 一致性比对

3.2.1 勾稽验证+md5方法

勾稽是一个小姑娘起的名字,在这里就是看一下左表不为NULL的left_table_num,右表不为NULL的right_table_num,两个表都有的 left_right_equal_num,如果这三个数相等就说明数据是一致的。反之数据肯定不一致,同时可以计算出不一致的条数。

md5:就是计算一行数据的md5值,把它当成key去做比对。尤其是在百亿数据规模的情况下,这种方法也使用。

************ 数据量一致性验证SQL ************* 注意:这里采用 full join

  1. select sum(case when left_table.record_key is not null or left_table.record_key !='' then 1 else 0 end) as left_table_num,
  2. sum(case when right_table.record_key is not null or right_table.record_key !='' then 1 else 0 end) as right_table_num,
  3. sum(case when left_table.record_key = right_table.record_key then 1 else 0 end) as left_right_equal_num
  4. from (
  5. select md5(
  6. concat(
  7. if(user_id is null, '-', cast(user_id as string)),
  8. if(user_name is null, '-', cast(user_name as string)),
  9. if(order_id is null, '-', cast(order_id as string)),
  10. if(city_id is null, '-', cast(city_id as string)),
  11. if(city_name is null, '-', cast(city_name as string)),
  12. if(字段n…… is null, '-', cast(字段n…… as string)),
  13. if(dt is null, '-', cast(dt as string))
  14. )
  15. ) as record_key
  16. from mart_online.fact_user_order_day
  17. where dt=20190413
  18. )left_table
  19. full outer join (
  20. select md5(
  21. concat(
  22. if(user_id is null, '-', cast(user_id as string)),
  23. if(user_name is null, '-', cast(user_name as string)),
  24. if(order_id is null, '-', cast(order_id as string)),
  25. if(city_id is null, '-', cast(city_id as string)),
  26. if(city_name is null, '-', cast(city_name as string)),
  27. if(字段n…… is null, '-', cast(字段n…… as string)),
  28. if(dt is null, '-', cast(dt as string))
  29. )
  30. ) as record_key
  31. from mart_test.fact_user_order_day
  32. where dt=20190413
  33. )right_table
  34. on left_table.record_key=right_table.record_key
  1. ************ 数据量一致性验证报表 *************
  2. [left_table_num]左表中的数据条数,[right_table_num]右表中的条数,[left_right_equal_num]两个表中相等的数据条数。
  3. 左表中有[5660]条数据和右表不一致!
  4. +--------------+---------------+--------------------+
  5. |left_table_num|right_table_num|left_right_equal_num|
  6. +--------------+---------------+--------------------+
  7. | 16358699| 16358699| 16353039|
  8. +--------------+---------------+--------------------+

3.2.2 暴力比对法

适合具有唯一ID的表,返回空说明验证准确。

  1. select online.*,
  2. test.* from(
  3. select id,
  4. user_id,
  5. user_name,
  6. order_id,
  7. city_id,
  8. city_name
  9. from mart_online.fact_user_order_day
  10. where dt='20190413'
  11. )online
  12. left outer join (
  13. select id,
  14. user_id,
  15. user_name,
  16. order_id,
  17. city_id,
  18. city_name
  19. from mart_test.fact_user_order_day
  20. where dt='20190413'
  21. ) test
  22. on test.id=online.id
  23. where test.user_id!=online.user_id
  24. or test.user_name!=online.user_name
  25. or test.order_id!=online.order_id
  26. or test.city_id!= online.city_id
  27. or test.city_name!= online.city_name

3.3 差异数据发现

发现差异数据的方法很多,这里只讲一个通用的方法:逐条比对法(假定两个表有唯一的ID,如果没有唯一ID,其实md5不一样的数据就不一致),这种方法适合小规模数据,当然我们真是实现的时候是结合一致性验证的情况,直接就能找到差异的数据并打印出来。

  1. select left_table.*,
  2. right_table.*
  3. from (
  4. select *
  5. from mart_online.fact_user_order_day
  6. where dt=20190413
  7. )left_table
  8. full outer join (
  9. select *
  10. from mart_test.fact_user_order_day
  11. where dt=20190413
  12. )right_table
  13. on left_table.id = right_table.id
  14. and left_table.dt = right_table.dt
  15. where COALESCE(left_table.user_id, 0) <> COALESCE(right_table.user_id, 0)
  16. or COALESCE(left_table.user_name, 0) <> COALESCE(right_table.user_name, 0)
  17. or COALESCE(left_table.order_id, 0) <> COALESCE(right_table.order_id, 0)
  18. or COALESCE(left_table.city_id, 0) <> COALESCE(right_table.city_id, 0)
  19. or COALESCE(left_table.city_name, 0) <> COALESCE(right_table.city_name, 0)
  20. or COALESCE(left_table.字段n……, 0) <> COALESCE(right_table.字段n……, 0)
  1. 不一致的条数:[5660],case如下表所示:
  2. +-------+----------------+------------------+---------------+---------------+
  3. |id |left_user_id |left_字段n…… |right_user_id |right_字段n…… |
  4. +-------+----------------+------------------+---------------+---------------+
  5. | 0| 1| 哇哈哈| 1| 养乐多|
  6. +-------+----------------+------------------+---------------+---------------+

四、总结

如上验数SQL,可以通过代码封装,自动生成,就可以做成自动化数据验证的小工具了。真实情况比较复杂,要考虑字段的识别,where条件,两个表是否有唯一ID,没有唯一ID如何处理等等。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/656493
推荐阅读
相关标签
  

闽ICP备14008679号