数据仓库-IP段关联计算优化-从优化原理到优化手段一一道来

 

为什么要优化?

营销活动指标体系需要用日志数据进行多维度分析,其中一个维度就是通过IP段获取到用户的所属地域进行分析,但IP段与其它字段的映射方式不同,IP段是一个范围,关联时是一对多关系,在资源集中使用时段,1万左右的数据量的耗时可达一小时以上,严重影响指标的及时性,所以要进行优化,来解决任务耗时高的问题

优化手段

1 减少参与计算的数据量

当前IP表中记录总数为 772845 条,但中国所使用的IP段仅有 91374 条,因此在统计时计,限制 country_name = '中国',能够有效的减少任务执行时间;

2 任务层面优化

数据仓库的计算引擎是MR,下面简单介绍下MapReduce计算模型

MapReduce计算模型

MapReduce是作为计算引擎出现的,在处理超大规模的数据集上,MapReduce性能可观,通过分布式计算,将大规模数据计算任务分解,MapReduce计算模型是由Map任务和Reduce任务组成,各自承担不同的功能

优化原理

思路:通过增加Map任务的数量,提高任务计算速度

通常来讲,表的一个分区就对应物理存储(HDFS)的一个文件(上图中的block块),也就对应一个Map任务;

这次优化就是通过构建表的二级、三级分区来增加物理存储文件的数量,从而间接的增加Map任务数量,让Map并行计算少量的数据,达到优化目的

二级分区:ip_category,将start_ip(起始IP)和end_ip(结束IP)按照固定范围划分,分区值A、B、C、D、E

三级分区:ip_seg1,取start_ip(起始IP)的第一段作为分区,分区值 198、199、202 ...

优化如下所示:

  • 优化后的表结构
CREATE TABLE IF NOT EXISTS ip_location_mapping_dispose_mf
(
    dw_gmt_create DATETIME COMMENT '数据仓库创建时间',
    gmt_modified  DATETIME COMMENT '记录修改时间',
    gmt_create    DATETIME COMMENT '记录创建时间',
    id            BIGINT   COMMENT '自增id,主键',
    start_ip      STRING   COMMENT 'IP段起始IP地址',
    end_ip        STRING   COMMENT 'IP段结束IP地址',
    start_ip_long BIGINT   COMMENT 'IP段起始IP十进制数',
    end_ip_long   BIGINT   COMMENT 'IP段结束IP十进制数',
    start_ip_seg  BIGINT   COMMENT 'start_ip片段',
    country_name  STRING   COMMENT 'IP所属国家',
    province_name STRING   COMMENT 'IP所属省份',
    city_name     STRING   COMMENT 'IP所属城市',
    isp_name      STRING   COMMENT '网络服务提供商',
    ext0          STRING   COMMENT '扩展字段',
    ext1          STRING   COMMENT '扩展字段',
    ext2          STRING   COMMENT '扩展字段',
    ext3          STRING   COMMENT '扩展字段',
    ext4          STRING   COMMENT '扩展字段'
) 
COMMENT 'IP所属地映射表-月表'
PARTITIONED BY
(
    ms            STRING   COMMENT '日期分区, 格式:yyyymm',
    ip_category   STRING   COMMENT 'ip分类:A B C D E',
    ip_seg1       BIGINT   COMMENT 'ip第1段分区'
);

  • 构建分区的sql
WITH t_clear_ip_location_mapping AS (
    SELECT  gmt_modified
            ,gmt_create
            ,id
            ,start_ip
            ,end_ip
            ,start_ip_long
            ,end_ip_long
            ,start_ip_seg
            ,country_name
            ,province_name
            ,city_name
            ,isp_name
            ,ext0
            ,ext1
            ,ext2
            ,ext3
            ,ext4
            ,CASE   WHEN start_ip_long >= 16777216 AND end_ip_long <= 2147483647 THEN 'A'
                    WHEN start_ip_long >= 2147483648 AND end_ip_long <= 3221225471 THEN 'B'
                    WHEN start_ip_long >= 3221225472 AND end_ip_long <= 3758096383 THEN 'C'
                    WHEN start_ip_long >= 3758096384 AND end_ip_long <= 4026531839 THEN 'D'
                    WHEN start_ip_long >= 4026531840 AND end_ip_long <= 4160749567 THEN 'E'
            END AS ip_category
            ,IF(SPLIT_PART(start_ip,'.',1) <> CAST(SPLIT_PART(end_ip,'.',1) AS BIGINT),'N','Y') AS is_equal_ipseg1
    FROM    ip_location_mapping_mf
    WHERE   ms = '${before_month_str}'
    AND     record_status = 0
    AND     country_name = '中国'
)

INSERT OVERWRITE TABLE ip_location_mapping_dispose_mf PARTITION (ms = '${before_month_str}',ip_category,ip_seg1)
SELECT  GETDATE() AS dw_gmt_create
        ,gmt_modified
        ,gmt_create
        ,id
        ,start_ip
        ,end_ip
        ,start_ip_long
        ,end_ip_long
        ,start_ip_seg
        ,country_name
        ,province_name
        ,city_name
        ,isp_name
        ,ext0
        ,ext1
        ,ext2
        ,ext3
        ,ext4
        ,ip_category
        ,CAST(SPLIT_PART(start_ip,'.',1) AS INT) AS ip_seg1
FROM    t_clear_ip_location_mapping
WHERE   is_equal_ipseg1 = 'N'
UNION ALL
SELECT  GETDATE() AS dw_gmt_create
        ,gmt_modified
        ,gmt_create
        ,id
        ,start_ip
        ,end_ip
        ,start_ip_long
        ,end_ip_long
        ,start_ip_seg
        ,country_name
        ,province_name
        ,city_name
        ,isp_name
        ,ext0
        ,ext1
        ,ext2
        ,ext3
        ,ext4
        ,ip_category
        ,CAST(SPLIT_PART(end_ip,'.',1) AS INT) AS ip_seg1
FROM    t_clear_ip_location_mapping
WHERE   is_equal_ipseg1 = 'N'
UNION ALL
SELECT  GETDATE() AS dw_gmt_create
        ,gmt_modified
        ,gmt_create
        ,id
        ,start_ip
        ,end_ip
        ,start_ip_long
        ,end_ip_long
        ,start_ip_seg
        ,country_name
        ,province_name
        ,city_name
        ,isp_name
        ,ext0
        ,ext1
        ,ext2
        ,ext3
        ,ext4
        ,ip_category
        ,CAST(SPLIT_PART(start_ip,'.',1) AS INT) AS ip_seg1
FROM    t_clear_ip_location_mapping
WHERE   is_equal_ipseg1 = 'Y'
;

  • 优化后的关联方式
select *
from(
  SELECT  MAX(buss_line) AS buss_line
          ,app_id
          ,MAX(product_name) AS app_name
          ,cookie_id
          ,uid
          ,MAX(channel) AS channel
          ,MAX(os) AS os
          ,MAX(device_brand) AS device_brand
          ,SPLIT_PART(MAX(ip),',',1,1) AS ip
          ,MAX(ip_long) AS ip_long
          ,MIN(spm_time) AS first_spm_time
          ,MAX(spm_time) AS last_spm_time
          ,COUNT(CASE WHEN action = '2' THEN 1 ELSE NULL END) AS visit_cnt
          ,COUNT(CASE WHEN action = '1' THEN 1 ELSE NULL END) AS click_cnt
          ,DATEDIFF(MAX(spm_time),MIN(spm_time),'ss') AS during_time
          ,SUM(CASE WHEN action = '4' AND events_id LIKE '%activity_during_visit%' AND events_params["duration_time"] >= '3' THEN 1 ELSE 0 END) AS is_exsit_3s_spm
          ,MAX(CASE WHEN ip_long >= 16777216 AND ip_long <= 2147483647 THEN 'A' WHEN ip_long >= 2147483648 AND ip_long <= 3221225471 THEN 'B' WHEN ip_long >= 3221225472 AND ip_long <= 3758096383 THEN 'C' WHEN ip_long >= 3758096384 AND ip_long <= 4026531839 THEN 'D' WHEN ip_long >= 4026531840 AND ip_long <= 4160749567 THEN 'E' END) AS ip_category
          ,MAX(CAST(SPLIT_PART(ip,'.',1) AS INT)) AS ip_seg1
  FROM    (
                          SELECT  buss_line
                                  ,app_id
                                  ,product_name
                                  ,cookie_id
                                  ,uid
                                  ,channel
                                  ,os
                                  ,device_brand
                                  ,ip
                                  ,spm_time
                                  ,action
                                  ,events_id
                                  ,events_params
                                  ,CAST(GETIPFROMSTRING(SPLIT_PART(ip,',',1,1)) AS INT) AS ip_long
                          FROM    dw_d2v_spm_markactivity_detail_hi
                          WHERE   ds = '${before_hour_date_str}'
                          AND     hs = '${before_hour}'
                      ) 
              GROUP BY app_id
                       ,uid
                       ,cookie_id
          ) s
  LEFT JOIN   (
                  SELECT  *
                  FROM    ip_location_mapping_dispose_mf
                  WHERE   ms = SUBSTR('${before_32day_date_str}',1,6)
              ) s_ip
  ON      s.ip_category = s_ip.ip_category
  AND     s.ip_seg1 = s_ip.ip_seg1
  WHERE   s.ip_long >= s_ip.start_ip_long
  AND     s.ip_long <= s_ip.end_ip_long

优化效果

分别对3万、30万、50万、80万的数据量进行了测试,对比优化前,综合效率提升35 ~ 40倍,优化效果明显

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值