大数据基础技能入门指南

news2024/11/29 20:35:30

cf7944cdf234c66117d3b6e17df898c6.gif

本文介绍了数据工作中数据基础和复杂数据查询两个基础技能。

5792f368cbb64867a0f9200d5d877741.png

背景

当下,不管是业务升级迭代项目,还是体验优化项目,对于数据的需求都越来越大。数据需求主要集中在以下几个方面:

  1. 项目数据看板搭建:特别是一些AB实验的看板,能直观呈现项目的核心数据变化

  2. 数据分析:项目启动前的探索挖掘以及项目后的效果分析
    但是,眼下存在的一个普遍矛盾是:日益增长的数据需求和落后的数据生产力之前的矛盾

俗话说,求人不如求己,掌握基础的数据技能对于技术同学(尤其是开发岗位的同学)并不是一件难事,只是缺少一个合适的入门指南。本文旨在让想学习数据处理的同学能快速入门。

a2b8b40a9ddb44c598ce9653f46af32b.png

基础技能

  数据基础

这一部分先介绍MaxCompute(原odps)平台进行数据处理开发的基础知识。

  • 表基础

表(table)是数据处理的起点和终点,因此能看懂别人的表,会创建自己的表是数据处理技能中最最基础的一环。

表的创建和修改

创建临时表:

-- 临时表命名建议以“tmp_”开头,odps会知道该表是临时表
-- 临时表的生命周期建议按需设置,不要设置太长,避免资源浪费
CREATE TABLE tmp_ut_cart_clk LIFECYCLE 7 AS 
SELECT  user_id
FROM    <用户浏览数据表>

创建正式表:

-- analytics_dw是odps的空间名,后面的是表名
-- 空间名.表名 才能确定唯一的数据表
-- 以下是一个实际案例
CREATE TABLE IF NOT EXISTS analytics_dw.ads_tb_biz_request_opt_1d
(
    bucket_id                       STRING COMMENT '分桶'
    ,os                             STRING COMMENT '系统'
    ,uv                             BIGINT COMMENT '分桶用户数'
    ,pv                             BIGINT COMMENT '页面访问pv'
    ,page_stay_time                 BIGINT COMMRNT '页面停留时间(ms)'
    ...
)
PARTITIONED BY       -- 分区
(
    ds                              STRING COMMENT '日期'
)
LIFECYCLE 30
;

注意 PARTITIONED BY 这是指定分区字段。分区在odps的数据处理中很重要,合理的选择分区会让数据查询速度快非常多。

简单理解 分区 就是文件目录的概念,目录信息越精确,需要查询的原始数据就越少,查询效率自然越高。

c415d47f549684a764a652529f7fb090.png

表的命名

如果我们计划要做一张需要定期更新并供他人使用的表,那么表的命名必须要符合一定规范。简单提炼下,我们日常数据处理经常遇到的表大概有4种:

类型

命名前缀

说明

维表

dim_xxxx

提供一些维度信息,一般是让其他表关联来补足部分信息

明细表

dwd_xxxx

经过清洗,过滤,字段处理过的表。仅仅是对客观行为的描述。是数据处理分析的基础

轻度汇总表

dws_xxxx

为了方面后续的数据分析,对部分维度进行聚合计算。讲大白话就是对dwd的部分维度进行group by聚合,轻度聚合表会丢失部分不那么重要的信息,能为后续的分析提供便利

应用层表

ads_xxxx

为上层应用提供数据的表。到了这一层,表中的数据基本不具备继续加工处理的能力。这些表中的数据一般都是用来配置报表,或者用来辅助决策的制定

对于开发同学来说,在需要我们自己创建表的情况下一般都是ads类型的表,表的命名可以按照下面的格式:

<空间名>.ads_<业务><二级业务/如有><功能/实验><数据统计周期/1d/7d/30d等等>

  • 基础查询

基础查询是数据处理的基础,这一步的主要工作包括数据的清洗和过滤,字段的加工拓展,为后续的数据处理打好坚实基础

下面是一个非常非常基础的查询sql:

SET odps.sql.mapper.split.size=2048; -- 默认是256(单位M)




SELECT  user_id
        ,page 
        ,time_stamp
        ...
FROM    <App用户使用明细表>
WHERE   ds = '${bizdate}'
AND     product = '<App名称>'
AND     event_type = '<事件类型:浏览\点击>'
AND     page = '<页面标识>'
;

如果查询的数据量巨大,那么查询时可能会遇到下面这个错误:

FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.RuntimeException: com.aliyun.odps.lot.cbo.plan.splitting.disruptor.InstExceedLimitException: task:M1 instance count exceeds limit 99999

这是因为odps是根据 数据存储大小/splitSize 来确定需要的实例数,但有个99999的上限,超限了就会报错。这时适当将splitSize调大一点即可(可以每次*2的幅度来调整)

字符串处理

查询过程中常见的字符串处理方法:

-- 单个条件
SELECT  IF(page = 'Page_XXX', 'y', 'n') AS is_page_xxx 


        -- 多个条件
        ,CASE WHEN hh <= 12 THEN '上午'
              WHEN hh > 12 AND hh <= 18 THEN '下午'
              ELSE '晚上'
        END AS 时间段


        -- 超级有用:提取args中的kv
        ,KEYVALUE(args, ',', '=', 'itemid') AS item_id


        -- 分割字符串(value为“a_b_c”这种有规律的字符串可以使用)
        ,SPLIT(value, '_') AS value_list  -- 这个是数组,可以使用索引 value_list[0]


        -- 去除空值(使用a,b,c中第一个不为NULL的值,否则用最后的空字符串)
        ,COALESCE(a, b, c, '') AS xxx


        -- 版本比较,超级实用
        ,IF(bi_udf:bi_yt_compare_version(app_version, '10.24.10') >= 0, 'y', 'n') AS is_target_version




        -- 解析JSON,提取目标信息
        ,GET_JSON_OBJECT(json_str, '$.section.item.name') AS item_name


        -- 类型转换
        ,CAST(user_id AS BIGINT) AS user_id


        -- 大小写转换
        ,TOUPPER(os) , TOLOWER(os)
日期处理

字符串处理中有关于日期时间的处理也比较常见,比如“查询最近7天的数据”,关于日期的常用函数如下:

-- 日期格式描述
  yyyy    年,4位
  MM      月,2位
  dd    日,2位
  hh/HH    12小时制/24小时制,2位
  mi    分钟,2位
  ss    秒,2位
  SSS    毫秒,3位
-- 通过上面这些格式就能在转化具体的日期时描述日期的格式:
20230807             yyyyMMdd
2023-08-07          yyyy-MM-dd
20230806 13:22:00            yyyyMMdd HH:mi:si




-- 单纯查询某个日期之前或者之后的数据
ds >= '20230807'




TO_DATE('20230807', 'yyyyMMdd')       -- 将日期字符串转为 datetime 实例,日期处理的基础


TO_CHAR(datetime, 'yyyyMMdd')          -- 将日期函数处理得到各种datetime转换为字符串


FROM_UNIXTIME(123456789)         -- 将unix时间戳转换成datetime对象      


-- 日期加减,自动处理进位关系
DATEADD(TO_DATE('20230807', 'yyyyMMdd'), 7, 'dd')    -- 20230814
DATEADD(TO_DATE('20230807', 'yyyyMMdd'), -7, 'dd')   -- 20230731


-- 2个日期间隔(第一个日期-第二个日期,结果可为负)
DATEDIFF(TO_DATE('20230807', 'yyyyMMdd'), TO_DATE('20230806', 'yyyyMMdd'), 'dd') -- 1


-- 提取指定时间
-- 在希望分小时段统计的场景下很实用
DATEPART(TO_DATE('2023-08-07 12:13:22', 'yyyy-MM-dd hh:mi:ss'), 'hh') -- 12
  • 关联查询

很多时候单一表的数据无法满足我们的需求,需要通过其他表来补充一些信息,这时就需要关联数据。在sql上表现为有Join操作。

常用的关联操作有 LEFT JOIN、RIGHT JOIN、INNER JOIN

-- 基本的join语法如下
SELECT  a.user_id 
        ,a.arg1
        ,a.args
        ,b.bucket_id
FROM    (
    SELECT  user_id
          ,arg1
          ,args 
  FROM  <用户手淘行为表>
) a
LEFT JOIN (
    SELECT  user_d
            ,bucket_id 
  FROM  <AB实验分流表>
) b
ON    a.user_id = b.user_id
;


-- left join、right join、inner join差别


left join:会保留左表的所有数据(在上面这个例子中左表就是 a,join左边的表),右表中没有匹配的数据将会丢失
right join:和left join相反会保留右表(b)的所有数据,左表中没有匹配的数据会丢失
inner join:最终只有两个表的交集部分会被保留下来

Join操作很容易出错,导致查询结果出错,而且这种错误有时非常隐蔽难以发现。主要原因就是匹配条件遗漏或者关联字段有重复值,出现多对多的情况,导致数据膨胀,进而影响了统计结果。为了避免出现问题,有几个建议:

  1. a、b表关联前先进行必要的数据清洗和去重,而不是先关联后处理

  2. 如果a、b表都是数据量很大的表,建议先随机抽取小样本数据生成临时表a'、b',然后对比最终表数据量和a'、b'的数据量大小是否符合预期

特别地,在小表关联大表的情况下,可以使用MapJoin提升效率,比如在一个每日成交表中有商品的类目信息,现在需要关联到对应的行业信息,而类目和行业的映射关系是一个很小的表,这种情况下就可以使用MapJoin提升任务的执行效率。

SELECT  /* + mapjoin(J2) */
        J1.*
        ,J2.industry
FROM    <订单表> J1
LEFT JOIN  
(
    SELECT  cate_level1_id
            ,industry
    FROM    <行业维表>
    WHERE   ds = '${bizdate}'
) J2
ON J1.cate_level1_id = J2.cate_level1_id
;
  • 聚合查询

聚合就是针对数据中的某些维度(系统、版本等)执行一系列计算返回单一值。一般在sql上体现为有Group By操作。一般我们数据处理(指标计算)的最后几步都离不开聚合操作。

-- 常见聚合函数
AVG(age) AS avg_age )    -- 平均值


SUM(cnt) AS total_cnt    -- 求和


MIN(age) AS min_age      -- 最小值


MAX(age) AS max_age      -- 最大值


COUNT(*) / COUNT(item_id)  -- 计数 count(*)不会忽略null,count(xx)会忽略null


COUNT(DISTINCT utdid)      -- 去重计数


COLLECT_SET(item_id)       -- 将去重后的item_id存在一个数组中


COLLECT_ARRAY(item_id)     -- 将item_id存在一个数组中(不去重)


PERCENTILE(duration, 0.95)  -- 求分位数

通常,我们在执行聚合时可能会有一些特殊的需求,比如我们想查询每日成交中每个省份的GMV同时还想查询所有省份的整体GMV。正常可能需要这么写:

SELECT  province  
    ,SUM(amount) AS gmv
FROM  <每日成交表>
GROUP BY province


UNION ALL


SELECT  '整体' AS province  
    ,SUM(amount) AS gmv
FROM  <每日成交表>

维度少的时候这么写没问题,但考虑下这个需求,我们想看每个省下面的每个城市的gmv,同时也想看这个省整体的gmv,同时也想看所有省份的gmv,这时再用上面的写法就会很繁琐。这时可以考虑使用CUBE或者GROUPING SETS来简化查询逻辑:

SELECT  IF(GROUPING(province) == 0, province, 'all') AS province
        ,IF(GROUPING(city) == 0, city, 'all') AS city
        ,SUM(amount) AS gmv
FROM  <每日成交表>
GROUP BY GROUPING SETS((), (province), (province, city))


  -- 下面是CUBE的示例


SELECT  IF(GROUPING(province) == 0, province, 'all') AS province
        ,IF(GROUPING(city) == 0, city, 'all') AS city
        ,SUM(amount) AS gmv
FROM  <每日成交表>
GROUP BY CUBE(province, city)


-- 说明:
-- GROUPING SETS:按照制定维度组合来做聚合
-- CUBE:按照相关维度的全排列来做聚合

最后再强调一句:数据查询时 一定要指定分区 一定要指定分区 一定要指定分区

  复杂数据查询

很多同学其实是具备sql的基本知识的,但是一旦数据查询稍微变复杂一点,就有点束手无策。这个很正常,因为复杂sql的可读性、可维护性本来就很。和开发思路类似解决这个问题的方法就是将复杂的逻辑的拆解为简单的过程,减少查询的套娃。个人推荐的方法主要有:临时表、odps script、cte表达式三种方式。

  • 临时表(临时查询使用)

将复杂过程的查询过程拆解,每个过程的查询结果保存为一张临时表,直至最终完成整个查询逻辑。这个方法在做数据分析时特别好用。

一般我们都是以天为单位来分析数据,可以按照下面的模板来做:

-- 步骤1 甚至可以写注释方面以后理解
-- 建议将关心的原始数据先清洗处理保存为临时表,方便后面做各种分析使用,提升效率
DROP TABLE IF EXISTS tmp_step1_${bizdate};
CREATE TABLE tmp_step1_${bizdate} LIFECYCLE 3 AS  -- 临时表生命周期不要设置太久,避免无意义的资源浪费
SELECT  a
        ,b
        ,c
FROM  <数据表1>
WHERE  <筛选条件>
;


-- 步骤2
DROP TABLE IF EXISTS tmp_step2_${bizdate};
CREATE TABLE tmp_step2_${bizdate} LIFECYCLE 3 AS 
SELECT  a
        ,b
        ,c
FROM  tmp_step1_${bizdate} 
;


-- ....


-- 关注的结果
SELECT  *
FROM  tmp_stepN_${bizdate}
GROUP BY xxx
;

说明:

  1. 临时表查询最好能写成无脑一键执行就能获得最终结果,这能节省大量的时间

  2. ${xxx} odps的参数写法,可以在执行sql前制定对应参数的值,然后替换掉整个sql中的对应参数,本质是字符串替换,一个sql中可以出现多个参数

  3. 为了让sql能反复执行,建表前需要确保相应的表没有被创建过(DROP TABLE)

  • ODPS SCRIPT(有局限性,不推荐)

有cte表达式后,不推荐该方法。简单示例如下:

@step1 :=
SELECT   XX 
FROM   XXXX;


@step2 :=
SELECT   YY 
FROM   @step1;
....


SELECT  *
FROM  @stepN;
  • CTE表达式(强力推荐,用过都说好)

CTE能让我们将复杂任务拆解,提升SQL的可读性、可维护性。此外CTE不仅可以用于临时查询,也能将任务发布为周期任务。日常的数据处理可以使用下面的模板:

WITH
step1 AS
(
  SELECT  XX
  FROM    XXXX
),


step2 AS 
(
  SELECT  YY
  FROM    step1
),


....


stepN AS 
(
  SELECT  ...
)                   -- 最后的这括号后面不要加 , 


INSERT OVERWRITE TABLE <存储表名> PARTITION (ds = '${bizdate}')  -- 一个WITH只支持一个INSERT
SELECT  *
FROM  stepN

15e10fbd1f34929c495441cf5fa806f4.png

写在最后

数据处理并不是神秘、难以掌握的技能。每个技术同学、产品同学都是可以学会基本的数据处理技能的。希望本文能帮助有需要的同学叩开数据处理的大门。

99c8488eb210d0495d4d6153060d15a6.png

团队介绍

我们是大淘宝技术「基础交易终端团队」,主要负责电商核心交易链路业务和平台的研发,包含:淘宝购物车、下单、订单、物流、逆向等电商核心基础能力及创新型业务。这里有世界一流的技术产品,有丰富的业务场景,服务于十亿级的消费者,这里有巨大的挑战等你来。作为阿里的一支明星团队,负责阿里电商平台的核心交易主链路,是阿里移动技术的基石,每年双十一核心链路保障。

现招聘移动端(Android/iOS)开发工程师,有前端开发经验者优先,有意者可以投递简历到:guzhan.pc@taobao.com

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095992.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法练习Day20】修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 修剪二叉搜索树将有序数组转…

Grade 5 Math

数形结合 5 2 3 https://download.csdn.net/download/spencer_tseng/88431286

深入理解 Java 中的 synchronized 关键字

引入多线程的重要性和挑战 可以参考另一篇文章 https://blog.csdn.net/qq_41956309/article/details/133717408 JMM&#xff08;Java Memory Model&#xff0c;Java 内存模型&#xff09; 什么是JMM JMM&#xff08;Java Memory Model&#xff0c;Java 内存模型&#xff09…

怎么在抖音上引流?分享五个抖音引流推广必备的几个方法

大家好&#xff0c;我是 小刘今天为大家分享的是抖音引流知识分享&#xff0c;今天咱们聊一些干货知识&#xff0c;绝对会让你们有一个重新的认知。抖音的流量大&#xff0c;是毋庸置疑的&#xff0c;抖音也是最早一批短视频平台。抖音于2017年上线&#xff0c;一开始主要是通过…

Golang学习记录:基础知识篇(一)

Golang学习&#xff1a;基础知识篇&#xff08;一&#xff09; 前言什么是Golang&#xff1f;Go语言的基础语法语言结构基础语法数据类型基础使用 前言 很久之前就想学Go语言了&#xff0c;但是一直有其他东西要学&#xff0c;因为我学的是Java嘛&#xff0c;所以后面学的东西…

配置VScode开发环境-CUDA编程

如果觉得本篇文章对您的学习起到帮助作用&#xff0c;请 点赞 关注 评论 &#xff0c;留下您的足迹&#x1f4aa;&#x1f4aa;&#x1f4aa; 本文主要介绍VScode下的CUDA编程配置&#xff0c;因此记录以备日后查看&#xff0c;同时&#xff0c;如果能够帮助到更多人&#xf…

操作系统导论-第四章作业(待更)

一、进程 进程就是运行中的程序&#xff0c;程序本身是没有生命周期的&#xff0c;它只是存储在磁盘上的一些指令&#xff08;或者一些静态数据&#xff09;&#xff0c;操作系统将这些指令和数据加载到内存中&#xff0c;使其运行起来。 1.1 虚拟化CPU技术 根据我们平时使用…

基于Java的共享充电宝管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

AI时代助力程序员与项目经理的双翼飞翔:从开发到成长的秘诀

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。2022年度博客之星评选TOP 10&#x1f3c6;&#xff0c;Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作…

企业网盘中支持在线编辑的有哪些选项?

企业网盘作为现代企业不可或缺的工具之一&#xff0c;为企业提供了便捷的文件存储和共享功能。而其中支持在线编辑的解决方案更是减少了对额外软件的依赖&#xff0c;使团队成员可以直接在浏览器中进行实时协作。 什么是在线编辑&#xff1f; 在线编辑是指用户无需下载文件&a…

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d 文章目录 00 论文工作1 论文方法1.1 条件生成微调1.2 维护3d表示 2 效果 0 0 论文工作 之前分享的工作主要尝试是从一个pre-trained 文生图的diffusion模型中去蒸馏知识&#xff0c;从而去维护一个3d的表示…

数据结构上机实验——栈和队列的实现、栈和队列的应用、进制转换、约瑟夫环问题

文章目录 栈和队列上机实验1.要求2.栈的实现&#xff08;以顺序栈为例&#xff09;3.队列的实现&#xff08;以顺序队列为例&#xff09;4.利用栈实现进制转换5.利用队列解决约瑟夫环问题6.全部源码Stack.hQueue.htest.cpp 栈和队列上机实验 1.要求 1.利用栈的基本操作实现将任…

docker-compose部署elk(8.9.0)并开启ssl认证

docker部署elk并开启ssl认证 docker-compose部署elk部署所需yml文件 —— docker-compose-elk.yml部署配置elasticsearch和kibana并开启ssl配置基础数据认证配置elasticsearch和kibana开启https访问 配置logstash创建springboot项目进行测试kibana创建视图&#xff0c;查询日志…

李宏毅生成式AI课程笔记(持续更新

01 ChatGPT在做的事情 02 预训练&#xff08;Pre-train&#xff09; ChatGPT G-Generative P-Pre-trained T-Transformer GPT3 ----> InstructGPT&#xff08;经过预训练的GPT3&#xff09; 生成式学习的两种策略 我们在使用ChatGPT的时候会注意到&#xff0c;网站上…

2023/10/15

文章目录 1.uniapp之Vue2升Vue3值得注意的几点1.1 页面生命周期的使用1.2 引入资源的方式 2. 浏览器本地存储之Cookie和webStorage3. CSS变量 var()的用法4. CSS之实现线性渐变背景5. 图片无法和文字对齐的正确解决方案6. 使用正则处理接口返回的富文本内的图片7. transition实…

Java练习题-获取数组元素最大值

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;Java练习题 &#x1f4ac;个人格言&#xff1a;不断的翻越一座又…

[cpp primer随笔] 11. 内联函数与constexpr函数

1. 内联函数 调用函数一般比对等价表达式求值要慢。因为调用函数除了对表达式求值外&#xff0c;还包含一系列过程&#xff0c;包括堆栈建立、拷贝实参、跳转执行等等。而在程序之中&#xff0c;通常存在一些优化规模较小、流程直接、却调用频率很高的函数&#xff0c;我们可以…

51系列—基于51单片机的集中抄表设计(代码+文档资料)

概述 自动抄表&#xff08;Automatic Meter Reading-AMR&#xff09;是指采用通讯和计算机网络等技术自动读取和处理表计数据。发展电能自动抄表技术是提高用电管理水平的需要&#xff0c;也是网络和计算机技术迅速发展的必然。在用电管理方面&#xff0c;采用自动抄表技术&am…

YOLOv5-QAT量化部署

目录 前言一、QAT量化浅析二、YOLOv5模型训练1. 项目的克隆和必要的环境依赖1.1 项目克隆1.2 项目代码结构整体介绍1.3 环境安装 2. 数据集和预训练权重的准备2.1 数据集2.2 预训练权重准备 3. 训练模型3.1 修改数据配置文件3.2 修改模型配置文件3.3 训练模型3.4 mAP测试 三、Y…

浅谈“智慧园区”

前言&#xff1a;国庆《中国智慧园区发展白皮书&#xff08;2022&#xff09;》&#xff0c;很全面的介绍智慧园区的起源、发展阶段、涉及内容、未来规划、竞争格局等。做了些笔记&#xff0c;这对在智慧园区工作的伙伴应该很有帮助&#xff0c;下面是笔记和一些公开资料的整合…