尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Hadoop离线数仓实战:全国酒店数据清洗、Hive分析与可视化

Hadoop离线数仓实战:全国酒店数据清洗、Hive分析与可视化 简介这份资源是面向大数据初学者与Hadoop实践者的完整项目案例围绕全国各省市酒店数据的分析与处理展开帮助读者掌握分布式存储与MapReduce编程的核心流程。项目以Java编写MapReduce程序结合HDFS完成数据导入与并行计算可统计酒店总数、省市分布、平均房价等指标适合课程设计、实训作业或自学练手。压缩包共79个文件约758KB包含21个java源码与21个class编译文件、7个xml配置、6组part-r-00000与_success输出结果、2个csv数据文件及properties、txt说明等覆盖从源码、配置到运行产物的完整链路。目前已有2096人学习下载。读者可据此了解数据清洗、Map与Reduce函数设计、作业提交与结果解读的完整思路并借助说明文档与输出样例快速复现实验积累海量数据处理经验。1. 全国酒店数据上 Hadoop从一堆 CSV 到能查能算的离线数仓手头拿到一份全国各省市酒店数据几十万到几百万行不等字段通常包括酒店名称、省份、城市、地址、星级、评分、评论数、价格区间。用 Excel 打开就卡死用 pandas 单机跑一次 group by 要等好几分钟而且换一个维度就得重跑一遍。这个标题要解决的就是这件事把散落的酒店明细数据搬进 Hadoop用 HDFS 存、MapReduce 或 Hive 算最终能按省份、城市、星级快速出统计结果。适合有 Java 或 SQL 基础、正在做课程设计或企业离线数仓入门的人。核心链路是数据清洗、上传 HDFS、建 Hive 外部表、写分析 SQL、导出结果。下面按我实际跑通的顺序拆开讲包括伪分布式搭建、字段处理、分区设计和几个容易翻车的地方。2. 环境选型与 Hadoop 伪分布式搭建单机也能跑通全链路2.1 为什么酒店数据分析用伪分布式就够全国酒店数据这个量级真实项目里可能上集群但个人开发或课程设计阶段伪分布式完全够用。伪分布式是 NameNode、DataNode、ResourceManager、NodeManager 都在一台机器上逻辑上跟集群一致作业提交到 YARN 的流程也完整走一遍。好处是调试方便坏处是内存吃紧所以 JVM 堆要调小。选型上Hadoop 3.x 比 2.x 更稳端口和默认配置有变化新手容易在 9870 和 50070 之间搞混。Hive 用 3.x 配 Tez 或 MapReduce 引擎都行酒店数据这种聚合查询MapReduce 引擎慢但稳Tez 快但要多配一步。我一般先用 MapReduce 引擎把链路跑通再换 Tez 提速。提示伪分布式搭建前先确认 JDK 版本Hadoop 3.x 要求 JDK 8 或 11JDK 17 会有模块访问问题。2.2 从零开始安装 Hadoop 与 Hive 的关键命令先建用户和目录改主机名和 hosts这些基础步骤网上教程很多不展开。重点说配置文件和启动顺序。# 创建 hadoop 用户并赋权 useradd -m hadoop passwd hadoop echo hadoop ALL(ALL) NOPASSWD:ALL /etc/sudoers # 解压安装包到 /opt tar -zxvf hadoop-3.3.6.tar.gz -C /opt/ chown -R hadoop:hadoop /opt/hadoop-3.3.6 # 配置环境变量 echo export HADOOP_HOME/opt/hadoop-3.3.6 /etc/profile echo export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin /etc/profile source /etc/profile核心配置文件有四个core-site.xml 设 fs.defaultFS 为 hdfs://localhost:9000hdfs-site.xml 设副本数为 1因为伪分布式只有一个 DataNodemapred-site.xml 设 mapreduce.framework.name 为 yarnyarn-site.xml 设 yarn.nodemanager.aux-services 为 mapreduce_shuffle。改完格式化 NameNode再启动。hdfs namenode -format start-dfs.sh start-yarn.sh jps # 应看到 NameNode、DataNode、ResourceManager、NodeManagerjps 少进程是常见问题先看日志目录下的 .log 文件多半是端口占用或内存不足。内存不足就改 hadoop-env.sh 里的 HADOOP_HEAPSIZE调到 512 或 1024。Hive 安装后要配 hive-site.xml指定 MySQL 存元数据或者用内嵌 Derby 先跑通。用 MySQL 的话要把 mysql-connector-java 放到 Hive 的 lib 目录并初始化 schema。schematool -dbType mysql -initSchema hive # 进入 CLI2.3 酒店数据字段与 Hive 表结构设计酒店数据常见字段和类型映射如下建表时按这个来避免后面查询类型转换报错。字段名原始类型Hive 类型说明hotel_name字符串STRING酒店名称province字符串STRING省份city字符串STRING城市star数字INT星级1-5score小数DOUBLE评分comment_count数字INT评论数price小数DOUBLE参考价建外部表指向 HDFS 上的数据目录这样删表不丢数据。CREATE EXTERNAL TABLE hotel_raw ( hotel_name STRING, province STRING, city STRING, star INT, score DOUBLE, comment_count INT, price DOUBLE ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE LOCATION /user/hadoop/hotel/data;分隔符要和 CSV 一致如果字段里有逗号先清洗成制表符或竖线。外部表的好处是数据还在 HDFS表只是映射。3. 数据清洗与上传 HDFS把脏 CSV 变成可查的表3.1 酒店数据常见的四类脏数据原始酒店数据几乎没有直接能用的。第一类是缺失评分或价格为空第二类是格式混乱价格带「¥」或「元」星级写成「五星」第三类是重复同一酒店多条记录第四类是异常值评论数为负或价格为零。这些不处理Hive 查询结果就是错的。清洗用 Python 在本地做因为 Hadoop 上写 MapReduce 清洗代码成本高小数据量本地处理更快。用 pandas 读 CSV逐列处理再写出干净的文件。import pandas as pd df pd.read_csv(hotel_raw.csv, encodingutf-8) # 去重 df.drop_duplicates(subset[hotel_name, city], inplaceTrue) # 价格清洗去掉货币符号转 float df[price] df[price].astype(str).str.replace(r[¥元,], , regexTrue) df[price] pd.to_numeric(df[price], errorscoerce) # 星级清洗中文数字转阿拉伯数字 star_map {一星: 1, 二星: 2, 三星: 3, 四星: 4, 五星: 5} df[star] df[star].replace(star_map) df[star] pd.to_numeric(df[star], errorscoerce) # 缺失值处理评分和价格用中位数填充星级缺失标记为 0 df[score].fillna(df[score].median(), inplaceTrue) df[price].fillna(df[price].median(), inplaceTrue) df[star].fillna(0, inplaceTrue) # 异常值过滤 df df[(df[comment_count] 0) (df[price] 0)] # 写出为制表符分隔避免字段内逗号冲突 df.to_csv(hotel_clean.tsv, sep\t, indexFalse, headerFalse)这段代码的关键点是 errorscoerce它把无法转换的值变成 NaN而不是直接报错中断。中位数填充比均值稳因为酒店价格分布偏斜。写出时不带表头因为 Hive 建表时已经定义了列。3.2 上传 HDFS 与分区目录规划清洗完的文件传到 HDFS。如果数据按省份分文件可以建分区表查询时只扫对应分区速度快很多。# 建目录 hdfs dfs -mkdir -p /user/hadoop/hotel/data # 上传 hdfs dfs -put hotel_clean.tsv /user/hadoop/hotel/data/ # 查看 hdfs dfs -ls /user/hadoop/hotel/data/如果要做分区表目录结构要按 province省份 来组织。hdfs dfs -mkdir -p /user/hadoop/hotel/partitioned/province广东 hdfs dfs -put guangdong.tsv /user/hadoop/hotel/partitioned/province广东/分区字段不能出现在数据文件里否则查询会多一列错位。这是新手最常踩的坑之一。3.3 用 Hive 外部表挂载数据并验证行数数据上传后建外部表指向目录然后 count 一下验证。CREATE EXTERNAL TABLE hotel_clean ( hotel_name STRING, city STRING, star INT, score DOUBLE, comment_count INT, price DOUBLE ) PARTITIONED BY (province STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t STORED AS TEXTFILE LOCATION /user/hadoop/hotel/partitioned; -- 修复分区元数据 MSCK REPAIR TABLE hotel_clean; -- 验证 SELECT COUNT(*) FROM hotel_clean;MSCK REPAIR 是必须的它扫描目录把分区信息写入元数据。如果 count 为 0先看目录名格式对不对再看分隔符是否匹配。用 TAB 分隔比逗号安全因为酒店名称里可能有逗号。4. 用 Hive SQL 做多维度分析省份、星级、价格带4.1 按省份统计酒店数量和平均评分这是最基础的维度聚合验证数据可用性。SELECT province, COUNT(*) AS hotel_cnt, ROUND(AVG(score), 2) AS avg_score, ROUND(AVG(price), 2) AS avg_price FROM hotel_clean GROUP BY province ORDER BY hotel_cnt DESC;如果数据量大这条 SQL 会触发 MapReduce 或 Tez 作业。看 YARN 的 8088 端口能追踪进度。结果里如果某个省 avg_score 异常低回去查清洗时是否有大量缺失被填了中位数。4.2 星级分布与价格带交叉分析酒店分析里星级和价格带交叉很有价值能看出不同档次的价格区间。SELECT star, CASE WHEN price 200 THEN 低 WHEN price 500 THEN 中 WHEN price 1000 THEN 高 ELSE 豪华 END AS price_band, COUNT(*) AS cnt FROM hotel_clean WHERE star 0 GROUP BY star, CASE WHEN price 200 THEN 低 WHEN price 500 THEN 中 WHEN price 1000 THEN 高 ELSE 豪华 END ORDER BY star, price_band;CASE WHEN 在 Hive 里写法固定注意 END 不能漏。这个查询能直接导出成报表用 Excel 做透视。4.3 城市排名与评论数 Top N找热门城市和头部酒店用窗口函数或排序取 Top N。SELECT city, COUNT(*) AS hotel_cnt, SUM(comment_count) AS total_comments FROM hotel_clean GROUP BY city ORDER BY total_comments DESC LIMIT 20;如果要每个省取前 3 城市用 row_number() over (partition by province order by ...)。Hive 对窗口函数支持良好但数据倾斜时某个 reduce 会卡住可以加 distribute by province 缓解。4.4 把 Hive 结果导出到本地或 HDFS分析结果要落地用 INSERT OVERWRITE DIRECTORY 导出。INSERT OVERWRITE DIRECTORY /user/hadoop/hotel/result/province_stat ROW FORMAT DELIMITED FIELDS TERMINATED BY , SELECT province, COUNT(*), ROUND(AVG(score), 2) FROM hotel_clean GROUP BY province;导出后在 HDFS 上是一个目录里面可能有多个 part 文件。用 hdfs dfs -getmerge 合并下载到本地。hdfs dfs -getmerge /user/hadoop/hotel/result/province_stat ./province_stat.csvgetmerge 会把目录下所有文件合并成一个本地文件方便后续用 Excel 或 Python 做可视化。5. 避坑与排查酒店数据跑 Hadoop 时最容易翻车的五件事5.1 中文乱码导致省份字段全变问号现象Hive 查询结果里省份显示为 ??? 或乱码。原因原始 CSV 是 GBK 编码Python 读时用了 utf-8或者 Hive 表没指定编码。解决Python 读文件时指定 encodinggbk写出时统一用 utf-8Hive 建表时加 SERDEPROPERTIES 指定编码或者干脆在清洗阶段转好。5.2 分区表查询返回空结果现象MSCK REPAIR 执行了但 SELECT 还是 0 行。原因目录名格式不对比如写成 province广东 但建表时分区字段名是 province或者目录层级多了一层。解决用 hdfs dfs -ls 逐层核对确保目录名和分区字段完全一致大小写敏感。另外检查数据文件是否真的在分区目录下而不是在父目录。5.3 YARN 作业卡在 ACCEPTED 不动现象SQL 提交后一直 ACCEPTED不进入 RUNNING。原因YARN 资源不足或者 NodeManager 没起来。解决jps 确认 NodeManager 在看 yarn-site.xml 的 yarn.nodemanager.resource.memory-mb 是否太小伪分布式调到 2048 或 4096。另外检查 mapreduce.map.memory.mb 和 mapreduce.reduce.memory.mb 是否超过容器上限。5.4 数据倾斜导致某个 Reduce 跑几小时现象大部分 Reduce 很快完成剩一两个卡在 99%。原因某个省份或城市的酒店数据量远超其他group by 时全分到一个 Reduce。解决开启 Hive 的负载均衡 hive.groupby.skewindatatrue或者对 key 加随机前缀打散再聚合。酒店数据里广东、浙江这种省份量大容易倾斜。5.5 外部表删了数据还在但表没了现象DROP TABLE 后 HDFS 数据还在但表元数据没了重新建表要重新 MSCK。原因外部表只删元数据不删数据这是设计如此。解决如果确实要删数据先 DROP TABLE 再 hdfs dfs -rm -r 目录。如果只是想重建表直接 CREATE EXTERNAL TABLE 指向原目录再 MSCK REPAIR 即可数据不会丢。6. 进阶技巧用 Python 把 Hive 结果做成可视化看板跑完 Hive 拿到省份统计、星级分布、城市排名后下一步是可视化。我一般用 Python 的 pyhive 或 impala 直连 Hive拉数据到 pandas再用 matplotlib 或 pyecharts 出图。pyhive 需要安装依赖连接时指定 host 和 port。from pyhive import hive import pandas as pd import matplotlib.pyplot as plt conn hive.Connection(hostlocalhost, port10000, databasedefault) df pd.read_sql(SELECT province, COUNT(*) AS cnt FROM hotel_clean GROUP BY province, conn) df df.sort_values(cnt, ascendingFalse).head(10) plt.barh(df[province], df[cnt]) plt.xlabel(Hotel Count) plt.title(Top 10 Provinces by Hotel Count) plt.tight_layout() plt.savefig(province_top10.png)pyhive 连 Hive 需要 HiveServer2 启动默认端口 10000。如果连不上先检查 hiveserver2 进程在不在再看防火墙。数据量大时不要全量拉在 SQL 里先聚合好。另一个技巧是用 Hive 的 EXPLAIN 看执行计划确认有没有走分区裁剪。酒店数据按省份分区后查询带 WHERE province广东 应该只扫一个分区EXPLAIN 输出里能看到 PartitionCount 为 1。如果为 -1 或很大说明分区没生效回去检查分区字段和查询条件是否匹配。最后说一个我自己的习惯每次跑完分析把 Hive SQL 和结果文件按日期归档因为酒店数据可能按月更新下次跑只需要换数据目录SQL 不用改。这个习惯帮我省了很多重复调试的时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表