大数据Hadoop学习七
博客二:Hive数据操作、复杂类型与性能优化策略
摘要: 本文是Hive入门的第二周学习总结,聚焦于数据的导入导出、复杂数据类型的应用,以及通过分区和分桶来优化查询性能的核心策略,是构建高效数据仓库的关键。
一、数据操作语言(DML):加载与导出
-
使用LOAD命令加载数据
LOAD DATA是一个高效的数据移动命令。-- 从本地Linux文件系统加载(复制文件) LOAD DATA LOCAL INPATH '/path/to/local/file.txt' INTO TABLE my_table; -- 从HDFS加载(移动文件) LOAD DATA INPATH '/path/on/hdfs/file.txt' INTO TABLE my_table; -- 覆盖加载(覆盖原有数据) LOAD DATA LOCAL INPATH '/path/to/local/file.txt' OVERWRITE INTO TABLE my_table;关键区别:
LOCAL关键字表示本地系统,否则是HDFS。从HDFS加载是移动操作,原始文件会消失;从本地加载是复制操作。 -
使用INSERT导出数据
INSERT语句提供了更灵活的数据导出方式。-- 将查询结果导出到本地目录,使用默认分隔符 INSERT OVERWRITE LOCAL DIRECTORY '/tmp/export1' SELECT * FROM employees; -- 导出到本地并指定分隔符 INSERT OVERWRITE LOCAL DIRECTORY '/tmp/export2' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT * FROM employees; -- 导出到HDFS(省略LOCAL关键字) INSERT OVERWRITE DIRECTORY '/hdfs/export' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT * FROM employees;
二、复杂数据类型:让数据模型更丰富
Hive支持三种主要的复杂数据类型,用于处理非标准化的数据。
-
Array(数组)
用于存储同类型的元素集合。
数据示例 (data.txt):zhangsan beijing,shanghai,tianjin lisi changchun,chengdu建表语句:
CREATE TABLE test_array ( name STRING, work_locations ARRAY<STRING> -- 定义数组类型 ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' -- 列分隔符 COLLECTION ITEMS TERMINATED BY ','; -- 数组元素分隔符常用查询:
-- 查询所有 SELECT * FROM test_array; -- 查询数组第一个元素 SELECT name, work_locations[0] AS first_city FROM test_array; -- 查询数组元素个数 SELECT name, SIZE(work_locations) AS city_count FROM test_array; -- 判断数组是否包含某元素 SELECT * FROM test_array WHERE ARRAY_CONTAINS(work_locations, 'tianjin'); -
Map(键值对)
用于存储K-V对。
数据示例:
1,John,father:Joe#mother:Mary#brother:David,28
建表语句:CREATE TABLE test_map ( id INT, name STRING, family_members MAP<STRING,STRING>, -- K是STRING, V是STRING age INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' -- 列分隔符 COLLECTION ITEMS TERMINATED BY '#' -- Map之间的分隔符 MAP KEYS TERMINATED BY ':'; -- K-V之间的分隔符常用查询:
-- 获取指定key的value SELECT id, name, family_members['father'] AS father FROM test_map; -- 获取所有key SELECT id, name, MAP_KEYS(family_members) AS relations FROM test_map; -- 获取所有value SELECT id, name, MAP_VALUES(family_members) AS names FROM test_map; -
Struct(结构体)
类似于一个微型的表,可以包含多个带有名称和类型的子列。
数据示例:
1#周杰轮:11
建表语句:CREATE TABLE test_struct ( id STRING, info STRUCT<name:STRING, age:INT> -- 定义结构体,包含子列 ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '#' -- 列分隔符 COLLECTION ITEMS TERMINATED BY ':'; -- 结构体子列分隔符常用查询:
-- 查询所有,包括子列 SELECT * FROM test_struct; -- 通过‘.’访问子列 SELECT id, info.name, info.age FROM test_struct;
三、性能优化利器:分区与分桶
-
分区表(Partitioned Table)
概念:根据某一列的值(如日期、地区)在HDFS上创建不同的子目录,查询时通过WHERE筛选分区,可以避免全表扫描,极大提升查询性能。-- 创建一个按日期分区的日志表 CREATE TABLE logs ( id INT, message STRING ) PARTITIONED BY (dt STRING) -- 分区字段 ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'; -- 向特定分区加载数据 LOAD DATA LOCAL INPATH './log_20231027.txt' INTO TABLE logs PARTITION (dt='2023-10-27'); -- 查询特定分区数据,效率极高 SELECT * FROM logs WHERE dt = '2023-10-27'; -
分桶表(Bucketed Table)
概念:根据指定列的Hash值模除分桶数量,将数据分散到固定数量的文件中。适用于大数据量的JOIN、采样和高效过滤。-- 开启分桶优化 SET hive.enforce.bucketing = true; -- 创建一个按用户ID分桶的表,分为4个桶 CREATE TABLE user_bucketed ( id INT, name STRING ) CLUSTERED BY (id) INTO 4 BUCKETS;关键点:分桶表的数据加载不能使用
LOAD DATA,必须使用INSERT SELECT来触发MapReduce计算Hash值,从而正确分桶。-- 正确方式:通过查询插入数据以实现分桶 INSERT OVERWRITE TABLE user_bucketed SELECT * FROM users;
四、总结
本周我们深入学习了Hive的数据操作,掌握了如何高效地导入导出数据。通过Array、Map、Struct三种复杂数据类型,我们能够更自然地在Hive中建模复杂业务数据。最后,分区和分桶作为Hive最核心的性能优化手段,帮助我们构建出高效、可扩展的数据仓库结构,为应对海量数据查询挑战打下了坚实基础。
下一周,我们将进入HiveQL的实战阶段,学习各类查询语法、函数,并最终完成一个从数据清洗、分析到可视化展示的完整项目案例。

浙公网安备 33010602011771号