一、Hive 认识
1. Hive 应用
问题:公司的经营状况?
主题一:财务
现金流
指标1.1:净现金流入/流出量
指标1.2:现金转换周期
预算执行状况
指标2.1:预算内成本控制
指标2.2:预算与实际支出的差异
主题二:产品
指标1:产品销售量
指标2:产品利润率
指标3:新产品开发周期
主题三:客户
老客户的流失率
指标1.1:重复购买率
指标1.2:客户满意度调查结果
新客户的留存率、转化率
指标2.1:新客户留存率
指标2.2:潜在客户到实际客户的转化率
主题四:员工
指标1:员工满意度
指标2:员工流失率
指标3:员工绩效评估
主题五:资产
指标1:资产负债率
指标2:固定资产周转率
指标3:存货周转率
问题 => 主题(拆分) => 指标 => HQL
2. Hive 定义
基于元数据和表数据对数据进行结构化治理的机制(数仓)
"基于元数据"的核心:获取Hive MetaStore指定Mysql存储的元数据并根据其解析HQL生成执行计划
"基于表数据"的核心:获取表数据并通过执行计划进行数据处理和结果存储和加载。
3. Hive 具体设计
关键组件
UI
:客户端提交查询。Compiler
:借助MetaStore获取存储在Mysql中的元数据信息解析查询块或表达式,生成执行计划。Execution engine
:管理计划的不同阶段之间的依赖关系(协调各操作的执行顺序),并在适当的大数据组件上执行这些阶段。
关键步骤详解
6.1步:
1.将执行计划提交到Hadoop作为一个MapReduce作业.
2.RM将作业分解为多个任务,并且分配给不同的集群节点去执行。
3.启动Map任务(读取输入数据,处理,输出结果)
4.启动Reduce任务(可选)(读取Map|Shffle端输出,处理,输出结果) => 决定了是MapOnly引擎还是MapReduce引擎
6.2步:
完成了一个Job,将数据加载到Hive表上。
6.3步:
Hive与HDFS进行交互,包括读取数据文件以进行查询,或将查询结果写入到HDFS。
7,8,9步:
一旦执行引擎完成了查询任务,结果需要被传回UI
体现了将查询结果有执行引擎处理并通过Hive驱动程序返回给用户界面的过程。
执行计划的变化过程
二、ETL——数仓构建核心环节
定义
将数据从各种数据源中提取出来,经过一系列处理和转换,最后导入到Hive委托存储的地方(例如:HDFS,Mysql等)
详解
Extract
从外部数据源读取不同数据格式(结构化,半结构化,非结构化)数据通过UI提交到Hive系统
如何从关系型数据库处拉取数据到近源层,使用JDBC技术写SQL语句:
`SELECT 字段列表 FROM A JOIN B JOIN C WHERE ...`
对于非关系型数据或其它格式的数据需要考虑其他方案。
Transform(+宽表)
列裁剪:使用 INSERT INTO ... SELECT 语句创建新表或视图。
数据清洗:移除无用或错误数据。
数据补全:修正残缺或错误数据。如 mlae 视为 male。 province city
数据变形:改变数据的格式。如 {province:Jiangsu, city:wuxi} 转为 Jiangsu | wuxi。
无法修正错误:删除记录或视为缺失后估算。如年龄 -3。
数据集大小对处理要求的影响
大数据集:尽量近似和估算
小数据集:尽量补全
Load
1. 将数据从DM层或者直接从源头加载到HDFS中。
2. 将物理计划传递给执行引擎,如MapReduce。
3. 获取处理后的结果或将处理后的结果写入HDFS。
ODS 近源层(`外部表`)
Extract后提取到的保持原始格式的数据被提取到ODS层,并在ODS层内经过一定的清洗和结构化。
DWD 明细层(`内部表`)
表合并(列),行不变
时间维度表
订单表 => pro_dwd.order_detail_by_date
订单详情表
省份表
城市表
店铺表 => pro_dwd.order_detail_by_add_shop
订单表
订单详情表
DWT 轻聚层
1.实现聚合操作
聚合操作包括对多个指标(如销售额、用户数等)在多个维度(如时间、地区、产品类别等)上进行统计汇总。
2.提取聚合需求共性
DWS 汇总层
指标对应的结果数据
DM 数据集市
涉及权限管理和权限申请,不同人看到不同权限的数据,也可以申请查看某份数据的权限。
## 如何理解在ODS上创建的是外部表,在DWD上创建的是内部表。
外部表的数据实际存储在外部系统(如HDFS)上,内部表的数据存储是由Hive管理的。
这是因为ODS层存储的原始数据还可能被其他应用所使用,而DWD层存储的经过转换、清洗和集成的数据专属于Hive。
关于"层"的概念:
1. "层"是逻辑概念,表示一个数据处理|存储环节,实际上存储在不同的服务器中。
2. "层"是基于数仓的概念,不依赖于任何引擎。
三、Hive 数据结构
(一)简介
1.存储位置
库、表的存储位置:
/user/hive/warehouse
【即配置hive.metastore.warehouse.dir
的文件夹路径地址】
| | 默认数据库default | 非default数据库 |
|--|--|--|
| 数据库位置 | | /user/hive/warehouse/数据库名字.db |
| 表位置 | /user/hive/warehouse/表名 | /user/hive/warehouse/数据库名字.db/表名 |
2.类型
数据的存储位置:
服务
Hive MetaStore:指定Derby|Mysql存储元数据信息,并与HDFS相关联。
开放API面向客户端供它们访问元数据信息。
存储
database_params:存放元数据参数配置
dbs:存放metadata元数据
(二)各数据类型详解
1.库:文件夹
2.表:文件夹
命名
内部表:hive_+含义
外部表:hiveext+含义
CTE|TEMPORARY TABLE|VIEW:含义|hivetmp+含义|hiveview+含义
分区表|分桶表:hivepar+含义
内部表与外部表
A.区别
内部表
1.HDFS中的数据由Hive管理,在Hive中删除表会同步删除数据。
2.在Hive中创建内部表之后,在HDFS中会自动创建内部映射路径:/hive312/warehouse/DB_NAME.db/TABLE_NAME
3.内部表在创建的时候,通常路径中还没有数据。
外部表
1.HDFS中的数据不由Hive管理,在Hive中删除表不会同步删除数据,要删数据必须去HDFS中手动删除。
2.在Hive中创建外部表之后,在HDFS中不会有内部映射路径,需要自行创建并指定location。(location为数据文件的上一级目录)
3.外部表在创建的时候,通常路径中已有数据。
B.选择
只在Hive中使用;频繁更新数据并希望这些操作自动管理 —— 内部表
数据由多个应用共享,例如Hive和Spark;数据不经常变化或数据更新由外部过程管理 —— 外部表
3.分区:文件夹
定义
分区字段名=分区字段值
基于一个或多个分区键进行分区,通常以日期进行分区。
分区表为内部表。
分区字段可以是原始表中的字段,也可以是通过表中的一个或多个字段计算出来的表达式。(日期 -> 年)。
若非原始字段,其本身也可以作为原始字段使用所有的SQL语句。
如何选用分区字段?
1.WHERE ... | ON ...
2.GROUP BY ... , DISTRIBUTE BY ... (确定Reducer) , cluster by ...(确定Reducer并在内部排序)
3.如果数据量大,由于分区本身(文件夹)的大小限制,会选择缩小分区字段的维度。
分类
1.静态分区(eg:客户按分区给数据)
需要为每个加载的数据集指定一个具体的分区(分区字段名=字段值)
适用于持续增长的新数据,例如对按月分区的数据,每个月增加一次分区即可。
2.动态分区(eg:项目初期,客户一次性给了大量数据)
适合处理包含大量分区的情况
作用
1.hive进行查询时就是文件流读文件,即使读一条数据也需要加载整个文件。
所以分区表将文件切割成更小的粒度,当需要针对局部数据进行检索、聚合等处理时,便于快速筛选出符合特定条件的数据,提高效率。
2.如果需要进行分组聚合的字段是分组字段,即直接对该分区作聚合,则直接设置combiner,无需设置reducer。
多级分区
GROUP BY year(order_time),month(order_time),weekofmonth(order_time)
=>从左到右分区从主到次
一级分区(year=2012)
二级分区(month=3)
三级分区(weekofmonth=2)
4.分桶:文件
定义
选择桶中的一个或多个列作为桶的依据,根据这些列的值对数据进行散列,然后根据散列值将数据分配到不同的桶中。
分桶的字段必须是表中已存在的字段,分桶数通常为2^n
默认采用原始字段值的hashcode%分桶数来决定该行数据会被拆分到几个桶。
目的
便于进行抽样,通过了解数据的分布状态来对数据进行全量分析。或者作为一部分数据集运行查询测试。
提升有join操作时的MR效率
如何确定分桶数量?
主要由采样率决定 : 10% -> 桶数定义为10
数据量越大,分桶越多。分桶越多,并行度越高。
分区倾斜严重,分桶能缓解。
四、Hive的配置与优化
配置: 优先级 重要程度
set config_item=value; 临时配置 1 ✔✔✔(个性化 执行优化)
set hive.server2.logging.operation.level=verbose|NONE; 开启|关闭日志(🔺)
hive-site.xml 自定义配置 2 ✔(服务 通用优化配置)
取hive-default.xml的头结构并且按hive_install.md进行个性化配置。
hive-default.xml 默认配置(模板) 3
优化:
Cost based Optimizer
1.通过估算不同查询策略的成本来选择执行计划,根据数据库中数据的变化动态调整计划。
2.在执行多表连接的查询时,会找出最优的连接顺序和连接算法.
五、Hive CLI
1.启用 Hive
HiveServer2 Beeline | HiveServer1 CLI | |
---|---|---|
Connection | beeline -u beeline -u jdbc:hive2://localhost:10000 | hive -h -p hive |
Query | beeline -e beeline -f | hive -e hive -f |
注意:beeline -u
输入的所有SQL语句前面不能有空白符。
beeline -u
刚开始连接上的时候会因为Hadoop的安全模式或者服务的延迟 导致开始可能会连接不上。
hive -e
适用于编写处理Hive的脚本,因为可以做临时连接(添加|删除分区...)
2.基本命令
!table 列出Hive中的所有表
!column <table_name> 列出Hive指定表中的所有列
!sh ls 直接在Hive调用Shell命令
dfs <HDFS CLI> 直接在Hive调用HDFS命令
!run <file_path> 运行绝对路径下的脚本
!dbinfo 查看当前数据库的信息
Hive的基本命令提供了一种快速访问和管理 Hive 的方式,无需编写完整的 SQL 查询。学会使用 Hive 基本命令实现简单快捷的操作。
3.数据类型(用于解析数据)
基础类型([]为较Mysql多出的)
字符:char,varchar,[string]✔
整数:tinyint,smallint,int✔,bigint
小数:float,double,numeric(m,n),decimal(m,n)✔
布尔:[boolean]✔
日期:date✔(YYYY-mm-dd 必须完整),timestamp(可以解析YYYY-mm-dd HH:MM:ss|YYYY-mm-dd HH:MM:ss.SSS|YYYY-MM-DD HH:MM:SS TZ 时区)✔
复杂类型(支持泛型)
数组:array<T> => 用于处理同类型数据,对原始数据做结构化映射的(先升维才方便降维)
键值对:map<K,V> => 用于处理有稳定映射关系的数据
结构体:struct<n1:T1,n2:T2,...> => 用于处理无稳定映射关系的数据
一般来说,键值对or结构体的键尽量简单,值可以有一定的复杂度。
嵌套复杂类型
数组结构体
array<struct<name:STRING,age:INT>> =>
[
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
]
特殊:
01 => string(若设置为int,会自动去除前导零)
2015-01 => date ❌(不完整) timestamp ❌(没有具体到秒) string ✔
4. 数据库
show databases;
create datebase if not exists yb12211;
use yb12211;
describe database yb12211;
alter database yb12211 set owner user dayongd;
drop datebase if exists yb12211;
5.数据表
A.建表操作
mkdir -p EXTERNAL_TABLE_DIR
hdfs dfs -put FILE_NAME EXTERNAL_TABLE_DIR
create [external] table if not exists TABLE_NAME(
id int,
name string,
time bigint,
isPartyMember boolean,
expectSalary decimal(10,2),
hobby array<string>,
scores map<string,int>,
address struct<province:string,city:string>
)
comment 'TABLE_USAGE'
PARTITIONED BY (partition_key STRING)
--- row format delimited
| fields terminated by ',' 字段分隔方式
| collection items terminated by ';' 集合项分隔方式
| map keys terminated by ':' 键值对分隔方式
| lines terminated by '\n' 行间分隔方式(还可能有'\r\n','\t',' '...)
|
--- row format serde 'CLASS_FULL_PATH'
CSV(123,张三,1698376651212,true,26238.45)
serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
with serdeproperties(
separatorChar=',',
quoteChar='"',(用于包围数据字段,避免数据内的符号被视为分隔符)
escapeChar='\\'(规避处理转义符)
)
regex
serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties(
'input.regex'='^(\\d+),(.*?),(\\d+),(true|false),(\\d+).(\\d+\.?\\d+?)$'
)
json
serde 'org.apache.hive.hcatalog.data.JsonSerDe'
hbase
serde 'org.apache.hadoop.hive.hbase.HBaseSerde'
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with sederproperties(
"hbase.columns.mapping"=":key,info:name,info:sex,info:age"
)
tblproperties("hbase.table.name"="test_serde");
stored as FILE_FORMAT(textfile|orc|parquet|sequencefile|JSONFile|CSV) 指定存储格式,文件的存储格式改变,可能要相应设置InputFormat和OutputFormat。
location 'EXTERNAL_TABLE_DIR'
tblproperties(
'skip.header.line.count'='1'
'skip.footer.line.count'='2'
'related_sql_table' = 'my_sql_table' 将Hive表与另一个数据库的表`my_sql_table`相关联
);
load data [local] inpath 'FILEDIR' [overwrite] into table DB_NAME.TABLE_NAME;
行格式的用法
delimited:以特定分隔符分隔的数据,可处理复杂数据
"123 Main St,Anytown,12345"
"math:90,science:85,english:95"
Serde:不得已才用
OpenCSVSerde:可以很好地处理包含引号和逗号的复杂 CSV 数据
不支持数据中有复杂的数据结构
"Jane Doe","[email protected]","555-1234","Street 123, Some City"
记忆:CSV格式要求
表头(可选)
CSV文件通常由多行组成,每行代表一个数据记录,字段内容可以包含在引号中(尤其是当字段值中包含分隔符时)
字段之间通常用,进行分隔,行之间通常用换行符进行分隔
RegexSerDe:适用于非标准或更复杂的文本数据格式和数据行中有较多无用数据的情况,通常面向日志
"[INFO] 2023-11-15 09:00:00 - Task started"
JsonSerDe:处理 json 格式的数据
{
"id": 2, "name": "Bob", "role": "Analyst", "salary": 50000}
记忆:JSON格式要求
键值对形式 + 字符串需用双引号括起来 + 逗号分隔
ROW FORMAT
便于对不同类型的数据进行建表,在采集数据到ODS的过程中发挥作用
LOAD
上传的文件类型不重要
LOCAL:有LOCAL表示文件位于Linux本地,执行后为拷贝数据
没有LOCAL表示文件位于HDFS中,执行后为直接移动数据
OVERWRITE:有OVERWRITE表示覆盖
没有OVERWRITE表示追加
LOAD DATA和LOCATION的区别
LOAD DATA:在hive312的目录下,将数据从文件系统(本地|HDFS)直接加载到Hive表中
LOCAL INPATH 复制
INPATH 移动
LOCATION:用于指定表的数据实际存储在哪个文件系统路径上
LOCAL INPATH 选择复制数据的原因是为了在本地文件系统下留存一份数据副本
INPATH 选择移动数据的原因是在HDFS中移动数据只设计元数据的更改,并且不涉及网络传输,效率更高。
常见函数
split("...",'SEPERATOR') 分隔
regexp_replace("...",'REGEX','REPLACE') 正则替换
explode(...) 列转行
表创建的三种方式
1. 先建表,再插入数据
INSERT INTO TABLE_NAME(FIELD1,FIELD2...) SELECT ...
2. 表结构和表数据一起创建
建表高阶语句(CTAS —— CREATE TABLE AS SELECT)
CTAS
CTAS 常用于筛选某表中的数据出来并作为新表的内容
CTAS 不能创建 分区表、分桶表、外部表
eg:筛选2015年之前的数据作为新表
create table hive_ext_test_before2015 as
select * from hive_ext_regex_test1w
where year(order_time) <= 2015;
CTAS WITH CTE(WITH 作为数据来源)
eg:筛选2015年之前的全部数据和2015年之后男性中订单数超过5条记录或订单总金额超过50000的数据
CREATE TABLE hive_test_before2015_and_male_over5or5w_after2015 AS
WITH
before2015 AS (
SELECT * FROM hive_ext_regex_test1w
WHERE YEAR(order_time)<=2015
),
agg_male_over5or5w AS (
SELECT user_id
FROM hive_ext_regex_test1w
WHERE YEAR(order_time)>2015 AND user_gender = '男'
GROUP BY user_id
HAVING COUNT(*) >= 5 OR SUM(order_amount) >= 50000
),
male_over5or5w AS (
SELECT * FROM hive_ext_regex_test1w A
INNER JOIN agg_male_over5or5w B
ON A.user_id = B.user_id AND YEAR(A.order_time)>2015
)
SELECT * FROM before2015
UNION ALL
SELECT * FROM male_over5or5w;
3. 单独创建表结构
CTL 完全复制表结构
CREATE TABLE employee_like LIKE employee;
-- 有时还需要添加内容
INSERT INTO employee_like SELECT * FROM employee;
创建临时表
临时表只对当前session有效,session退出后自动删除
表空间位于/tmp/hive-(安全考虑),根据Modify的时间查找对应的临时表文件。
如果创建的临时表和已创建的常规表表名相同,优先使用临时表
CREATE TEMPORARY TABLE TABLE_NAME(...) | AS SELECT ... ✔ | LIKE ...
创建视图
视图本质是一条复杂的公用的查询语句,实际上并不存储数据,查询视图实际上是在查询背后的基础表。
DROP VIEW IF EXISTS hive_view_test2020
CREATE VIEW IF NOT EXISTS hive_view_test2020 AS SELECT * FROM hive_ext_regex_test1w
WHERE year(order_time)=2020;
CTE & TEMPORARY TABLE & VIEW & SUBQUERY 的区别
VIEW :简化复杂查询,可以在多个查询中重复使用
SUBQUERY : 简化复杂查询,通常是特定于一个主查询的
TEMPORARY TABLE : 短期数据处理 复杂查询的中间结果 预聚合数据存储
CTE : 单次查询使用。
B. 删除/修改表
DROP TABLE IF EXISTS employee [WITH PERGE];
With PERGE直接删除(可选),否则会放到 .Trash目录
TRUNCATE TABLE employee;
清空表数据
修改表是可以在创建表之后进行追加描述的。
ALTER TABLE employee RENAME TO new_employee;(修改表名,常用于数据备份)
ALTER TABLE c_employee SET TBLPROPERTIES ('key'='value');
常见的表属性
'comment':用于提供关于表的描述性注释。
'serde':指定用于序列化和反序列化数据的序列化/反序列化器。
'location':指定表的物理存储位置。
'inputformat':指定输入数据的格式。
'outputformat':指定输出数据的格式。
'external':指示表是否为外部表(外部表的数据存储在外部位置,不受表删除操作的影响)。
...(可设置的表属性一般可通过DESCRIBE FORMATTED TABLE_NAME查看)
key不一定已存在:可以新建属性,也可以对已有属性进行修改。
新建属性通常起到的使标记或描述性的作用,而不是改变表的实际行为的配置。
ALTER TABLE employee_internal SET SERDEPROPERTIES ('field.delim' = '$');
ALTER TABLE c_employee SET FILEFORMAT RCFILE; -- 修正表文件格式
通常用于拉链表的情况
-- 修改表的列操作
ALTER TABLE employee_internal CHANGE old_name new_name STRING; -- 修改列名
ALTER TABLE c_employee ADD COLUMNS (work string); -- 添加列
ALTER TABLE c_employee REPLACE COLUMNS (name string); -- 替换
C.查看表信息
show tables; 查看所有表
SHOW TABLES LIKE 'TABLE_NAME' 快速检查是否存在某表
desc inner_tab_employee; 查看表结构(字段名称、类型等)
desc formatted inner_tab_employee; 获取表的详细信息(包括分区信息、字段信息、表属性、存储信息等)
show create table inner_tab_employee; 获取创建表的完整SQL语句
D.分区表
定义:partitioned by(PAR_FIELD_NAME DATA_TYPE, ...)
drop table if exists hive_internal_par_ext_regex_test1w;
create table if not exists hive_internal_par_ext_regex_test1w(
user_id int,
user_gender string,
order_time timestamp,
order_amount decimal(10,2)
)
partitioned by (year int)
row format delimited
fields terminated by ','
stored as textfile;
静态分区
1. 简单文本处理:
-- 从文件中筛选2012年的数据
cat test1w.log | awk '/2012-/{print $0}'>test2012.log
-- 将该数据上传到该表的2012年的分区下
load data local inpath '/root/hive/data/course/test2012.log'
overwrite into table hive_internal_par_ext_regex_test1w partition(year=2012);
- 复杂数据处理:
INSERT OVERWRITE TABLE sales PARTITION(year=2023, month=3) SELECT ... FROM another_table WHERE ...
动态分区 优先级
SET hive.exec.dynamic.partition = true; -- 1.会话 ✔
SET hive.exec.dynamic.partition.mode = nonstrict;
hive-site.xml -- 2.个性化配置
hive-default.xml -- 3.为所有配置项提供默认配置
INSERT OVERWRITE TABLE hive_internal_par_ext_regex_test1w PARTITION (year)
SELECT *, year FROM hive_ext_regex_test1w where year(order_time)>=2014;
RegexSerDe
不适用动态分区- SELECT 子句必须出现分区键(year),分区键可以为自定义的表中未出现字段。
- 必须指定分区键的原因是因为需要确定数据应该放入哪个分区中。
虚拟分区的创建:只能使用动态分区的语法,并且需要指定值。
动态分区和静态分区的区别:
静态分区:
分区键值必须在插入数据时明确指定
可以向一个分区内导入数据
动态分区:
分区键值在插入数据时动态指定
可以向多个分区内导入数据
查看分区信息
SHOW PARTITIONS TABLE_NAME;
手动添加分区
ALTER TABLE hive_internal_par_ext_regex_test1w ADD PARTITION(year=2021);
可以将符合数据结构的文件直接放到分区的路径下,从而实现分区数据的添加。
手动删除分区
ALTER TABLE hive_internal_par_ext_regex_test1w DROP PARTITION(year=2021);
eg:设置一个定时任务,定时删除三年前同月份的分区,并添加当年新月份的数据(一个月结束之后才能获取到该月完整的分区数据)
dt=$(date -d '-1 month' '+%F')
del_year=$(date -d "$dt -3 year" '+%Y')
del_month=$(date -d "$dt -3 year" '+%m')
add_year=$(date -d '+%Y')
add_month=$(date -d '+%m')
hive -e "ALTER TABLE hive_internal_par_ext_regex_test1w DROP PARTITION(year=$del_year,month=$del_month);"
if [ $? -eq 0 ];then
echo "SUCCESS TO DROP PREVIOUS PARTITION"
else
echo "FAIL TO DROP PREVIOUS PARTITION"
fi
hive -e "ALTER TABLE hive_internal_par_ext_regex_test1w ADD PARTITION(year=$add_year,month=$add_month);"
if [ $? -eq 0 ];then
echo "SUCCESS TO ADD NEW PARTITION"
else
echo "FAIL TO ADD NEW PARTITION"
fi
E.分桶表
clustered by (FIELD_NAME) INTO 2 BUCKETS
create table if not exists hive_internal_par_cluster_ext_regex_test1w(
user_id int,
user_gender string,
order_time timestamp,
order_amount decimal(10,2)
)
partitioned by (year int)
clustered by (order_time) into 4 buckets
row format delimited
fields terminated by ','
stored as textfile;
INSERT OVERWRITE TABLE hive_internal_par_cluster_ext_regex_test1w PARTITION(year)
SELECT *, year FROM hive_ext_regex_test1w where year(order_time)>=2014;
分桶抽样
随机抽样基于随机列
SELECT * FROM TABLE_NAME TABLESAMPLE(BUCKET 3 OUT OF 4 ON rand()) s;
随机抽样基于指定列(使用分桶列更高效)
SELECT * FROM TABLE_NAME TABLESAMPLE(BUCKET 3 OUT OF 32 ON id) s;
** 基于随机列和指定列的区别:
基于随机列的抽样提供了数据的随机和均匀代表性,适合于需要估计整个数据集的参数时。
基于指定列的抽样则适用于对数据集的特定部分感兴趣的情况,例如分析特定区域的销售数据或特定时间段的用户行为。
** 如何理解`BUCKET x OUT OF y`?
即将原本的桶分成y份后的顺序的第x个。
假设Num Buckets=4,x=2,y=8,明显桶的份数不够8份,因此将4个桶切分为8份,并且获取到第二份的数据。
![bucket抽样](./assets/bucket%E6%8A%BD%E6%A0%B7.png)
bucket的顺序是A1,B1 , C1 , D1 , A2 , B2 , C2 , D2
假设y<Num Buckets,那么直接假设合并即可。
未抽样数据: 抽样数据:
2014,945 2014,234
2015,931 2015,210
2016,858 1/4 2016,205
2017,909 ===> 2017,220 ===> 对每个分区数据进行抽样
2018,911 2018,224
2019,928 2019,224
临时表
如何判断该表是否为临时表?
通过命名看出来,如果有_tmp_的命名则是临时表;
SHOW CREATE TABLE TABLE_NAME;
使用环境:
Hive UI
Tableau(数据呈现),Zeppelin(交互)
案例1:建立一张内部表
数据:Michael|Montreal,Toronto|Male,30|DB:80|Product:DeveloperLead
create table if not exists inner_tab_employee(
name string,
places array<string>,
info struct<gender:string,age:int>,
scores map<string,int>,
dept_pos map<string,string>
)
row format delimited
fields terminated by '|'
collection items terminated by ','
map keys terminated by ':'
lines terminated by '\n'
stored as textfile;
load data local inpath '/root/hive/data/course/employee.txt' overwrite into table yb12211.inner_tab_employee;
案例2:利用hive完成词频统计
hdfs dfs -ls /hive_data/hive_cha01
hdfs dfs -mkdir /hive_data/hive_cha01/wild_call
hdfs dfs -put The_Call_of_the_Wild.txt /hive_data/hive_cha01/wild_call
create external table if not exists internal_table_wild_call(
line string
)
stored as textfile
location '/hive_data/hive_cha01/wild_call';
SELECT word,count(*) as word_count
FROM internal_table_wild_call
lateral view explode(split(regexp_replace(e,'[^a-zA-Z ]+',''),' '))A as word
where length(word)>0
group by word
order by word_count;
```
词频统计原理:
regexp_replace(e,'[^a-zA-Z ]+','') 去除非字母字符
split(...) 拆分成单词
lateral view(explode(...)) 将单词列表拆分成行格式,再将每个单词转换成一个独立的行。
没有ORDER时,默认单词从a-z排序的原因是按键排序
有ORDER时,总共会有两个stage(MapReduce任务),第一个是分组聚合,第二个是排序。
由于排序是对全局进行排序,并且一个job中通常具有不止一个的Reducer,Reducer进行需要先进行合并落盘之后才能进行排序。