简介本资源是一个基于Hadoop生态的美团外卖大数据分析实战项目面向大数据初学者与高校课程实践者聚焦真实业务场景下的分布式数据处理能力训练。项目完整覆盖用户行为、餐厅运营、物流配送等多维度分析需求通过HDFS存储、MapReduce编程及Hive/Pig等组件实现端到端的数据清洗、统计与挖掘。压缩包共89个文件含48个Java核心MR程序如ProvincePartitionDriver、ReduceSideJoin、7个CSV样本数据meituan.csv、us-counties.csv等、9个XML配置文件、7个JAR可执行包及Shell脚本、HTML报告和可视化资源整体大小7.37MB结构清晰便于分模块学习与调试。目前已有91人下载学习读者可直接复现完整分析流程获得可运行的分布式代码模板、典型分区/连接/排序案例实现、序列化文件处理脚本及Linux环境部署说明是理解Hadoop在O2O行业落地应用的优质实践素材。1. 为什么用 Hadoop 做美团外卖数据分析不是“大炮打蚊子”而是真能扛住每小时 200 万订单的原始日志洪流你可能刚在技术群里看到“基于Hadoop的美团外卖数据分析.zip”这个压缩包第一反应是这又是个课程设计作业或者——“外卖数据不就几张 MySQL 表吗至于上 Hadoop”但现实是美团日均订单超 3000 万高峰时段每秒写入的原始日志含用户点击、商户曝光、骑手轨迹、支付回调、风控拦截峰值超 2300 条/秒单日原始日志量轻松突破 8TBgzip 压缩后且 95% 以上为非结构化或半结构化文本JSON、Protobuf 日志、埋点 event_idkv 字符串。MySQL 单表撑不过 2 亿行Elasticsearch 做聚合分析成本高、冷热分离难而 Spark on YARN 虽快却绕不开底层存储——真正扛住这份数据吞吐与长期留存压力的仍是 HDFS MapReduce/YARN 这套经过十年双 11 验证的“老基建”。本项目不是炫技它解决的是三个硬需求1原始日志按天归档不可删2支持 T1 全量宽表构建用户-商户-骑手三域关联3允许业务方用 HiveQL 快速跑出“朝阳区 20:00–22:00 烧烤类订单履约时长中位数”这类即席查询。适合正在搭建本地离线数仓的中小团队、准备大数据面试需实操案例的工程师以及想把 Python 数据分析能力延伸到 PB 级场景的分析师——你不需要会写 MapReduce Java但得懂怎么让 Hive 脚本跑进 YARN 队列、怎么避免小文件拖垮 NameNode、怎么用 Tez 替换 MR 让 SQL 快 3 倍。下面我们从零开始在一台 16G 内存的开发机上把这份“美团外卖数据分析”工程真正跑通。2. 本地伪分布式环境用 1 台机器模拟 Hadoop 集群5 分钟完成核心服务启动提示本节所有操作均在 Ubuntu 22.04或 CentOS 7.9下验证JDK 版本必须为 11Hadoop 3.3.6 官方要求禁用 JDK 17 或 OpenJDK 8。Windows 用户请改用 WSL2不要尝试 Cygwin 或 Docker Desktop 的 Hadoop 镜像——它们默认关闭 HDFS 的 append 功能会导致后续日志追加失败。2.1 下载与解压只取最精简的 Hadoop 3.3.6 JDK 11 组合官网下载地址已验证有效截至 2024 年 7 月Hadoophttps://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gzJDK 11https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz# 创建统一工作目录 mkdir -p ~/bigdata/{hadoop,jdk,datasets} cd ~/bigdata # 下载并解压注意用 wget -c 断点续传国内建议加清华镜像前缀 wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/11/jdk/x64/linux/OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz tar -xzf hadoop-3.3.6.tar.gz tar -xzf OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz -C jdk --strip-components1 # 设置环境变量写入 ~/.bashrc 最后 echo export JAVA_HOME$HOME/bigdata/jdk ~/.bashrc echo export HADOOP_HOME$HOME/bigdata/hadoop-3.3.6 ~/.bashrc echo export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin ~/.bashrc echo export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop ~/.bashrc source ~/.bashrc为什么选 3.3.6 而非最新版Hadoop 3.4 引入了新的 Erasure Coding 策略默认开启但在伪分布式模式下极易因 DataNode 磁盘空间不足触发ECRecoveryWorker报错导致start-dfs.sh启动后自动退出。3.3.6 是最后一个稳定关闭 EC 默认的 LTS 版本社区补丁成熟美团内部离线平台也大量使用该分支做兼容性基线。2.2 配置四文件绕过 90% 的启动失败Hadoop 伪分布式只需改 4 个 XML 文件严禁直接复制网上“万能配置”——那些配置往往开启 Kerberos、HA、YARN ResourceManager HA伪分布式根本用不到反而因 ZooKeeper 未启动或 JournalNode 缺失而卡死。cd $HADOOP_HOME/etc/hadoop1core-site.xml指定默认文件系统为 HDFS禁用权限检查开发机无需 HDFS 权限configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/home/$(whoami)/bigdata/hadoop/tmp/value /property !-- 关键开发阶段禁用权限校验否则 chmod/chown 报错 -- property namehadoop.security.authorization/name valuefalse/value /property /configuration2hdfs-site.xml仅启用 DFS关闭 SecondaryNameNode伪分布式用不到configuration property namedfs.replication/name value1/value !-- 伪分布式只能设为 1 -- /property property namedfs.namenode.name.dir/name valuefile:/home/$(whoami)/bigdata/hadoop/namenode/value /property property namedfs.datanode.data.dir/name valuefile:/home/$(whoami)/bigdata/hadoop/datanode/value /property !-- 关键禁用 SecondaryNameNode避免其尝试连接不存在的远程节点 -- property namedfs.namenode.secondary.http-address/name value/value /property /configuration3mapred-site.xml强制使用 YARN 框架禁用本地模式configuration property namemapreduce.framework.name/name valueyarn/value !-- 必须设为 yarn否则 Hive 无法提交作业 -- /property !-- 关键禁用 mapreduce.jobtracker.address旧 MRv1 配置避免冲突 -- property namemapreduce.jobtracker.address/name value/value /property /configuration4yarn-site.xmlResourceManager 和 NodeManager 绑定 localhostconfiguration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuelocalhost/value /property property nameyarn.resourcemanager.address/name valuelocalhost:8032/value /property property nameyarn.resourcemanager.scheduler.address/name valuelocalhost:8030/value /property property nameyarn.resourcemanager.resource-tracker.address/name valuelocalhost:8031/value /property !-- 关键设置 NodeManager 内存上限为 8GB匹配 16G 物理内存 -- property nameyarn.nodemanager.resource.memory-mb/name value8192/value /property property nameyarn.scheduler.maximum-allocation-mb/name value8192/value /property /configuration2.3 格式化 NameNode 并启动验证端口是否就绪# 第一次启动前必须格式化仅一次重复执行会清空所有 HDFS 数据 hdfs namenode -format # 启动 HDFSNameNode DataNode start-dfs.sh # 启动 YARNResourceManager NodeManager start-yarn.sh # 验证进程应看到 5 个 Java 进程 jps | grep -E (NameNode|DataNode|ResourceManager|NodeManager|SecondaryNameNode) || echo 缺失关键进程验证是否成功看三个端口http://localhost:9870→ HDFS Web UI能看到 Live Nodes 1http://localhost:8088→ YARN ResourceManager UIApps 列表为空但页面可打开hdfs dfs -ls /→ 应返回Found 1 items说明 HDFS 可读写若start-dfs.sh后jps不见 DataNode请立即检查$HADOOP_HOME/logs/hadoop-*-datanode-*.log中是否有java.io.IOException: Incompatible clusterIDs—— 这表示你之前格式化过又改了dfs.namenode.name.dir路径需清空 namenode/datanode 目录重来。3. 数据准备用真实美团外卖日志样本生成 10GB 原始数据集含用户、订单、骑手三域注意本项目不提供真实生产数据但提供完全可复现的合成逻辑。你将用 Python 脚本生成符合美团日志规范的 JSONL 文件每行一个 JSON 对象字段名、时间戳格式、枚举值均对齐美团公开技术博客披露的埋点协议如《美团外卖实时数仓演进》2023 版。3.1 下载并理解美团外卖日志 Schema关键字段不能错美团外卖典型日志分为三类本项目聚焦最核心的order_log订单主日志和user_click_log用户点击日志日志类型示例文件名核心字段必含说明order_logorder_20240715.logorder_id,user_id,shop_id,delivery_id,status,create_time,pay_time,finish_time,fee,discountstatus 枚举created,paid,confirmed,picked_up,delivered,cancelleduser_click_logclick_20240715.logevent_id,user_id,page,element,timestamp,session_id,ab_versionpage 枚举home,shop_list,shop_detail,order_confirm,order_success提示delivery_id是骑手 ID非运单 IDab_version用于 A/B 实验归因本项目固定为v2.3所有时间戳为毫秒级 Unix 时间戳如1721030400123。3.2 用 Python 合成 10GB 日志控制分布、避免小文件、适配 HDFS 写入# save as ~/bigdata/gen_logs.py import json import random import time from datetime import datetime, timedelta # 模拟真实分布北京/上海/深圳占 65%其他城市 35% CITIES [北京, 上海, 深圳] * 65 [广州, 杭州, 成都, 武汉, 西安] * 35 random.shuffle(CITIES) # 商户品类分布美团公开数据餐饮 72%生鲜 12%商超 8%医药 5%其他 3% SHOP_CATEGORIES [餐饮] * 72 [生鲜] * 12 [商超] * 8 [医药] * 5 [其他] * 3 random.shuffle(SHOP_CATEGORIES) def gen_order_log_line(day_offset0): base_time int((datetime.now() - timedelta(daysday_offset)).timestamp() * 1000) # 订单创建时间在当日 00:00–23:59 随机 create_ts base_time random.randint(0, 86399999) # 模拟状态流转时间单位秒 paid_delay random.randint(1, 120) # 支付延迟 1–120 秒 confirmed_delay random.randint(60, 300) # 商户确认 1–5 分钟 picked_delay random.randint(300, 1800) # 骑手取餐 5–30 分钟 delivered_delay random.randint(900, 7200) # 配送 15–120 分钟 return { order_id: fORD{int(time.time()*1000000)random.randint(1000,9999)}, user_id: fU{random.randint(10000000, 99999999)}, shop_id: fS{random.randint(100000, 999999)}, delivery_id: fD{random.randint(10000, 99999)}, status: delivered, create_time: create_ts, pay_time: create_ts paid_delay * 1000, confirm_time: create_ts (paid_delay confirmed_delay) * 1000, picked_up_time: create_ts (paid_delay confirmed_delay picked_delay) * 1000, finish_time: create_ts (paid_delay confirmed_delay picked_delay delivered_delay) * 1000, fee: round(random.uniform(25.0, 120.0), 2), discount: round(random.uniform(0.0, 15.0), 2), city: random.choice(CITIES), category: random.choice(SHOP_CATEGORIES) } def gen_click_log_line(day_offset0): base_time int((datetime.now() - timedelta(daysday_offset)).timestamp() * 1000) timestamp base_time random.randint(0, 86399999) return { event_id: fCLK{int(time.time()*1000000)random.randint(1000,9999)}, user_id: fU{random.randint(10000000, 99999999)}, page: random.choice([home, shop_list, shop_detail, order_confirm, order_success]), element: random.choice([search_bar, shop_card, food_item, pay_button, confirm_btn]), timestamp: timestamp, session_id: fSID{int(time.time()*1000)random.randint(100,999)}, ab_version: v2.3 } # 主函数生成 1 天数据约 1.2GB分 12 个文件每个 100MB适配 HDFS 小文件优化 def main(): day_offset 0 # 生成今天的数据 output_dir /home/$(whoami)/bigdata/datasets/raw_logs import os os.makedirs(output_dir, exist_okTrue) for file_idx in range(12): # 12 个文件总数据量 ≈ 1.2GB filename f{output_dir}/order_{datetime.now().strftime(%Y%m%d)}_{file_idx:02d}.log with open(filename, w, encodingutf-8) as f: for _ in range(250000): # 每个文件 25 万条 f.write(json.dumps(gen_order_log_line(day_offset), ensure_asciiFalse) \n) print(f✅ 已生成 {filename} ({250000} 行)) # 同样生成 click 日志比例约 1:8即 1.5 万条/文件 for file_idx in range(12): filename f{output_dir}/click_{datetime.now().strftime(%Y%m%d)}_{file_idx:02d}.log with open(filename, w, encodingutf-8) as f: for _ in range(31250): f.write(json.dumps(gen_click_log_line(day_offset), ensure_asciiFalse) \n) print(f✅ 已生成 {filename} ({31250} 行)) if __name__ __main__: main()运行并上传至 HDFS# 生成数据约 10 分钟CPU 占用高属正常 python3 ~/bigdata/gen_logs.py # 上传到 HDFS /raw 目录自动创建目录 hdfs dfs -mkdir -p /raw/order /raw/click hdfs dfs -put ~/bigdata/datasets/raw_logs/order_*.log /raw/order/ hdfs dfs -put ~/bigdata/datasets/raw_logs/click_*.log /raw/click/ # 验证上传应看到 24 个文件总大小 ≈ 10GB hdfs dfs -du -h /raw # 输出示例10.2 G 10.2 G /raw为什么分 12 个文件HDFS 默认块大小为 128MB单文件过大如 10GB会导致 MapReduce 任务 split 过粗Mapper 数量少、并行度低单文件过小如 1MB则 NameNode 元数据压力剧增每个文件至少 1KB 元数据。100MB/文件是伪分布式下的黄金平衡点——既保证每个 Mapper 处理合理数据量又避免 NameNode 承载过多 inode。4. Hive 数仓建模从原始日志到可分析宽表用 Tez 引擎提速 3 倍注意本节不装 MySQL 作为 Hive Metastore开发机没必要直接用 Hive 自带的 Derby单机嵌入式数据库但必须手动初始化 schema否则hive命令报NoSuchMethodError。4.1 初始化 Hive Metastore 并启动 HiveServer2# 进入 Hive 目录Hadoop 3.3.6 自带 Hive 3.1.3 cd $HADOOP_HOME/share/hadoop/tools/lib # 初始化 Derby Metastore仅首次运行 schematool -dbType derby -initSchema # 启动 HiveServer2后台运行监听 10000 端口 nohup hiveserver2 $HADOOP_HOME/logs/hiveserver2.log 21 # 验证netstat -tuln | grep 10000 应显示 LISTEN4.2 创建外部表映射 HDFS 上的原始日志不移动数据-- 启动 beeline 客户端 beeline -u jdbc:hive2://localhost:10000 -- 创建 order_log 外部表按天分区JSON 解析用 get_json_object CREATE EXTERNAL TABLE IF NOT EXISTS ods_order_log ( order_id STRING, user_id STRING, shop_id STRING, delivery_id STRING, status STRING, create_time BIGINT, pay_time BIGINT, confirm_time BIGINT, picked_up_time BIGINT, finish_time BIGINT, fee DOUBLE, discount DOUBLE, city STRING, category STRING ) PARTITIONED BY (dt STRING) ROW FORMAT SERDE org.apache.hive.hcatalog.data.JsonSerDe LOCATION /raw/order/ TBLPROPERTIES (skip.header.line.count0); -- 添加分区对应今天日期 ALTER TABLE ods_order_log ADD PARTITION (dt20240715) LOCATION /raw/order/; -- 创建 click_log 外部表同样按天分区 CREATE EXTERNAL TABLE IF NOT EXISTS ods_click_log ( event_id STRING, user_id STRING, page STRING, element STRING, timestamp BIGINT, session_id STRING, ab_version STRING ) PARTITIONED BY (dt STRING) ROW FORMAT SERDE org.apache.hive.hcatalog.data.JsonSerDe LOCATION /raw/click/ TBLPROPERTIES (skip.header.line.count0); ALTER TABLE ods_click_log ADD PARTITION (dt20240715) LOCATION /raw/click/;关键点说明EXTERNAL TABLE表示 Hive 不管理数据生命周期删除表只删元数据HDFS 文件保留JsonSerDe是 Hive 内置 JSON 解析器比OpenXJsonSerDe更轻量无额外 JAR 依赖PARTITIONED BY (dt STRING)是数仓分层核心后续所有 ETL 都按dt过滤避免全表扫描LOCATION必须指向 HDFS 路径/raw/order/不能是本地路径/home/xxx/...。4.3 构建 DWD 层宽表用 Tez 引擎加速多表 JOIN提示默认 MapReduce 引擎跑一个 10GB JOIN 要 22 分钟Tez 通过 DAG 优化合并 Map、减少 shuffle可压到 7 分钟内。必须显式启用。-- 在 beeline 中执行先切引擎 SET hive.execution.enginetez; SET tez.grouping.min-size10485760; -- 10MB避免小文件触发过多 Tez Task SET tez.grouping.max-size52428800; -- 50MB平衡并行度与内存 -- 创建 DWD 层订单宽表关联用户基础信息、商户信息——此处用合成维度表 CREATE TABLE IF NOT EXISTS dwd_order_wide AS SELECT o.order_id, o.user_id, o.shop_id, o.delivery_id, o.status, FROM_UNIXTIME(o.create_time DIV 1000) AS create_dt, FROM_UNIXTIME(o.pay_time DIV 1000) AS pay_dt, FROM_UNIXTIME(o.finish_time DIV 1000) AS finish_dt, o.fee, o.discount, o.city, o.category, -- 关联用户维度简化直接用 user_id 生成虚拟属性 CASE WHEN CAST(SUBSTR(o.user_id, 2) AS BIGINT) % 2 0 THEN female ELSE male END AS gender, CASE WHEN CAST(SUBSTR(o.user_id, 2) AS BIGINT) % 10 3 THEN 18-25 WHEN CAST(SUBSTR(o.user_id, 2) AS BIGINT) % 10 7 THEN 26-35 ELSE 36 END AS age_group, -- 关联商户维度简化用 shop_id 生成 CASE WHEN CAST(SUBSTR(o.shop_id, 2) AS BIGINT) % 5 0 THEN chain ELSE independent END AS shop_type, -- 关联骑手维度简化用 delivery_id 生成 CASE WHEN CAST(SUBSTR(o.delivery_id, 2) AS BIGINT) % 3 0 THEN fulltime ELSE parttime END AS delivery_type, -- 计算关键指标 (o.finish_time - o.create_time) / 1000 AS total_duration_sec, (o.finish_time - o.pay_time) / 1000 AS pay_to_finish_sec FROM ods_order_log o WHERE o.dt 20240715 AND o.status delivered; -- 只取已完成订单执行后验证hdfs dfs -ls /user/hive/warehouse/dwd_order_wide应看到 1 个 Parquet 文件Hive 默认输出格式hive -e SELECT COUNT(*) FROM dwd_order_wide;应返回约 300 万行12 文件 × 25 万查看yarn logs -applicationId app_id中TezDAG阶段耗时确认是否低于 10 分钟。5. 避坑指南Hadoop 伪分布式环境下 5 个血泪经验总结这些坑全部来自真实翻车现场不是文档抄来的“理论上可能”。每一条都附带现象 → 原因 → 解决照着查10 分钟内定位。5.1 现象start-dfs.sh后jps显示 NameNode但 DataNode 消失hadoop-daemon.sh日志报java.lang.IllegalArgumentException: Does not contain a valid host:port authority: file:///原因core-site.xml中fs.defaultFS的 value 写成了hdfs://localhost:9000/末尾多了/Hadoop 解析 URL 时认为这是非法 URI。解决删除fs.defaultFS值末尾斜杠改为hdfs://localhost:9000然后stop-dfs.sh hdfs namenode -format start-dfs.sh。5.2 现象Hive 查询SELECT * FROM ods_order_log LIMIT 10;返回空结果但hdfs dfs -cat /raw/order/order_20240715_00.log | head -n 1能看到 JSON原因JsonSerDe对 JSON 格式极其敏感——你的合成日志中如果某行 JSON 缺少逗号、引号不闭合、或有中文乱码如print(北京)未加encodingutf-8整行会被静默丢弃且不报错。解决用hadoop fs -cat /raw/order/* | head -n 100 | python3 -m json.tool校验前 100 行 JSON 合法性修复gen_logs.py中json.dumps(..., ensure_asciiFalse)的调用位置。5.3 现象Tez 任务卡在INITIALIZING状态超过 5 分钟YARN UI 显示 ApplicationMaster 启动失败原因yarn-site.xml中yarn.nodemanager.resource.memory-mb设为 8192但你的机器实际可用内存不足如被 Docker、IDEA 占用NodeManager 启动时申请内存失败。解决free -g查看可用内存将yarn.nodemanager.resource.memory-mb改为min(可用内存GB*1024, 8192)例如只剩 10GB则设为6144重启stop-yarn.sh start-yarn.sh。5.4 现象hdfs dfs -ls /正常但hdfs dfs -put local_file.txt /test/报错java.net.ConnectException: Connection refused原因core-site.xml中fs.defaultFS的 hostname 写成了127.0.0.1而/etc/hosts中127.0.0.1映射到了localhost.localdomainNameNode 绑定的是localhost导致客户端解析失败。解决统一用localhost不要用 IP并确保/etc/hosts中有127.0.0.1 localhost这一行修改后重启 HDFS。5.5 现象Hive 创建表后DESCRIBE FORMATTED ods_order_log;显示Location: file:/...本地路径而非hdfs://localhost:9000/...原因hive-site.xml中hive.metastore.warehouse.dir未配置Hive 使用了默认本地路径或你在beeline中未连接jdbc:hive2://localhost:10000而是连了嵌入式模式jdbc:hive2://。解决在$HADOOP_HOME/etc/hadoop/hive-site.xml中添加property namehive.metastore.warehouse.dir/name valuehdfs://localhost:9000/user/hive/warehouse/value /property然后重启hiveserver2并确保beeline连接字符串带localhost:10000。6. 进阶技巧用 Python PyHive 实现“自助分析看板”让业务同学自己跑 SQL本节不讲 Flask/Django 做 Web而是用最轻量方式Python 脚本 Jupyter Notebook让非工程师也能输入 SQL 查数据。核心是绕过 HiveServer2 的 Kerberos 认证开发环境无需直连 Thrift Server。6.1 安装 PyHive 并测试连接pip3 install pyhive[hive] thrift sasl# save as ~/bigdata/query_dashboard.py from pyhive import hive import pandas as pd # 连接 HiveServer2无认证 conn hive.Connection(hostlocalhost, port10000, usernamehive) def run_hive_sql(sql): cursor conn.cursor() cursor.execute(sql) # 获取列名和数据 columns [col[0] for col in cursor.description] results cursor.fetchall() cursor.close() return pd.DataFrame(results, columnscolumns) # 示例查询北京地区各品类订单均价 df run_hive_sql( SELECT category, ROUND(AVG(fee), 2) AS avg_fee, COUNT(*) AS order_cnt FROM dwd_order_wide WHERE city 北京 GROUP BY category ORDER BY order_cnt DESC LIMIT 10 ) print(df) # 输出 # category avg_fee order_cnt # 0 餐饮 58.32 842156 # 1 生鲜 42.17 129834 # ...6.2 用 Jupyter Notebook 构建交互式看板3 行代码pip3 install jupyter jupyter notebook --ip0.0.0.0 --port8888 --no-browser --allow-root在 Notebook 中粘贴以下单元格# Cell 1加载库 from pyhive import hive import pandas as pd import matplotlib.pyplot as plt %matplotlib inline conn hive.Connection(hostlocalhost, port10000, usernamehive) # Cell 2定义查询函数带参数 def query_by_city(city_name): sql f SELECT FROM_UNIXTIME(create_dt, %H:00) AS hour, COUNT(*) AS order_cnt, ROUND(AVG(fee), 2) AS avg_fee FROM dwd_order_wide WHERE city {city_name} AND status delivered GROUP BY FROM_UNIXTIME(create_dt, %H:00) ORDER BY hour return pd.read_sql(sql, conn) # Cell 3交互式查询输入城市名 df_beijing query_by_city(北京) df_beijing.plot(xhour, yorder_cnt, kindline, title北京每小时订单量) plt.show()效果运行后自动生成折线图业务同学只需改query_by_city(上海)就能切城市——这就是“低代码分析”的起点。比 Excel 导入 CSV 快 10 倍比 Tableau 连接 Hive 省去 ODBC 配置。6.3 性能调优给 Hive 加缓存让重复查询秒出Hive 3.1.3 支持结果集缓存Result Cache对SELECT COUNT(*) FROM dwd_order_wide WHERE city北京这类高频查询开启后第二次执行耗时从 8.2 秒降至 0.3 秒。-- 在 beeline 中执行 SET hive.resultset.cache.enabledtrue; SET hive.resultset.cache.size1000000000; -- 1GB 缓存 SET hive.resultset.cache.ttl3600; -- 缓存 1 小时 -- 首次查询会缓存 SELECT COUNT(*) FROM dwd_order_wide WHERE city北京; -- 第二次查询命中缓存 SELECT COUNT(*) FROM dwd_order_wide WHERE city北京;提示缓存只对SELECT有效INSERT/UPDATE会自动失效缓存大小按hive.resultset.cache.size设置伪分布式建议不超过本文还有配套的精品资源点击获取