基于Hadoop生态的OLAP解决方案:从原理到实战的深度解析
引言:OLAP与Hadoop的“天作之合”
在大数据时代,企业的核心需求已经从“存储数据”转向“挖掘数据价值”。OLAP(在线分析处理)作为数据分析的核心技术,承担着将大规模数据转化为可行动 insights 的关键角色。而Hadoop生态系统凭借其分布式存储(HDFS)、并行计算(MapReduce/Spark)和生态兼容性,成为构建企业级OLAP平台的首选基础架构。
本文将从OLAP基础概念出发,深入解析Hadoop生态中主流OLAP组件的原理与实战,结合数学模型、代码案例和应用场景,为你呈现一套完整的“基于Hadoop的OLAP解决方案”。无论你是数据工程师、分析师还是架构师,都能从本文中获得可落地的实践指南。
一、OLAP基础:从概念到多维数据模型
在讨论Hadoop生态的OLAP解决方案前,我们需要先明确OLAP的核心概念,以及它与OLTP(在线事务处理)的本质区别。
1.1 OLAP vs OLTP:两种数据处理模式的对比
| 维度 | OLTP(在线事务处理) | OLAP(在线分析处理) |
|---|---|---|
| 核心目标 | 处理日常事务(如订单、支付) | 分析数据价值(如销售趋势、用户行为) |
| 数据特征 | 小批量、高并发、实时性要求高 | 大批量、低并发、延迟容忍度高 |
| 数据模型 | 关系型(ER模型),强调数据一致性 | 多维型(星型/雪花模型),强调分析效率 |
| 查询类型 | 简单查询(如SELECT * FROM orders WHERE id=1) | 复杂查询(如按时间、地区、品类汇总销售额) |
| 典型系统 | MySQL、Oracle、PostgreSQL | Hive、Spark SQL、Presto、Kylin |
1.2 OLAP的核心:多维数据模型
OLAP的本质是多维分析,即从“维度”(描述数据的属性)和“度量”(可量化的指标)两个角度拆解数据。常见的多维数据模型包括:
(1)星型 schema(Star Schema)
- 事实表(Fact Table):存储业务事件的量化数据(如订单金额、销量),包含多个维度外键。
- 维度表(Dimension Table):存储维度的描述信息(如时间、地区、用户),结构扁平。
示例(电商场景):
- 事实表:
orders(order_id, user_id, product_id, order_time, amount) - 维度表:
users(user_id, age, gender, country)、products(product_id, category, brand)、time(time_id, year, month, day)
(2)雪花 schema(Snowflake Schema)
- 维度表被进一步规范化(拆分),减少数据冗余,但会增加查询时的join次数。
- 示例:
products表拆分为products(product_id, category_id, brand_id)、categories(category_id, category_name)、brands(brand_id, brand_name)。
(3)Cube(立方体):预计算的多维数据集
Cube是OLAP的“终极武器”——它预计算所有维度组合的度量值,将复杂的查询转化为“查表”操作。例如,对于“时间(年/月/日)、地区(国家/省份/城市)、品类(一级/二级/三级)”三个维度,Cube会预计算:
- 所有单维度组合(如年销售额、国家销售额)
- 所有二维组合(如年+国家销售额、月+品类销售额)
- 所有三维组合(如年+国家+品类销售额)
Cube的数学表示:
假设一个OLAP系统有k个维度,每个维度有n_i个层级(如时间维度有年、月、日3个层级),则Cube的大小为:
Cube Size=∏i=1k(ni+1)
\text{Cube Size} = \prod_{i=1}^k (n_i + 1)
Cube Size=i=1∏k(ni+1)
(注:+1表示“所有层级的汇总”,如时间维度的“总计”)
示例:若有3个维度,每个维度有2个层级,则Cube大小为(2+1)*(2+1)*(2+1)=27,即预计算27种维度组合的度量值。
二、Hadoop生态中的OLAP组件:全景图与核心选型
Hadoop生态系统提供了丰富的OLAP组件,覆盖从批处理OLAP到实时OLAP、从交互式查询到高并发查询的全场景需求。以下是主流组件的对比:
| 组件 | 类型 | 核心优势 | 适用场景 |
|---|---|---|---|
| Hive | 批处理OLAP | 兼容SQL、生态完善、支持大规模数据 | 离线报表、批量数据分析 |
| Spark SQL | 交互式OLAP | 内存计算、低延迟、支持流批一体 | 实时报表、 ad-hoc查询(即席查询) |
| Presto | 跨数据源OLAP | 多数据源联邦查询、高吞吐量 | 跨Hive/MySQL/Redis等数据源的分析 |
| Impala | 实时OLAP | MPP架构、低延迟、兼容Hive元数据 | 实时Dashboard、高并发查询 |
| Kylin | 预计算OLAP | Cube预计算、亚秒级查询 | 高并发、固定维度的报表(如电商GMV统计) |
| Trino | 云原生OLAP | 分布式架构、支持S3/GCS等云存储 | 云环境下的大规模数据分析 |
| Doris | 实时数仓OLAP | 高吞吐导入、低延迟查询、支持实时更新 | 实时数据仓库、用户行为分析 |
三、核心组件深度解析:原理与实战
3.1 Hive:批处理OLAP的“老大哥”
(1)Hive的核心原理
Hive是基于Hadoop的SQL引擎,将SQL转化为MapReduce/Tez/Spark任务执行。其核心架构包括:
- ** metastore**:存储元数据(如表结构、分区信息)。
- Driver:解析SQL、生成执行计划、优化查询。
- Execution Engine:执行任务(支持MapReduce、Tez、Spark)。
Hive的执行流程(以MapReduce为例):
- 解析(Parse):将SQL转化为抽象语法树(AST)。
- 绑定(Bind):从metastore获取元数据,将AST转化为逻辑计划。
- 优化(Optimize):通过**Cost-Based Optimization(CBO)**优化逻辑计划(如谓词下推、列修剪)。
- 生成物理计划:将逻辑计划转化为MapReduce任务(如GroupBy转化为Map阶段的局部聚合+Reduce阶段的全局聚合)。
- 执行(Execute):提交任务到Hadoop集群,获取结果。
Mermaid流程图:
(2)Hive的OLAP优化:从MapReduce到LLAP
Hive的传统问题是延迟高(MapReduce的磁盘IO开销大),为此社区推出了两大优化:
- Tez执行引擎:替代MapReduce,采用**有向无环图(DAG)**执行任务,减少磁盘IO,提升并行度。
- LLAP(Live Long and Process):保持查询的中间结果在内存中,支持增量查询和并发查询,将延迟从分钟级降低到秒级。
示例:使用Hive LLAP查询月销售额
-- 创建分区表(按年/月/日分区)
CREATE TABLE orders (
order_id INT,
user_id INT,
product_id INT,
category_id INT,
amount DECIMAL(10,2)
)
PARTITIONED BY (year INT, month INT, day INT)
STORED AS PARQUET;
-- 加载数据(假设数据已上传到HDFS)
LOAD DATA INPATH '/user/hive/orders/2023/10/01' INTO TABLE orders PARTITION (year=2023, month=10, day=01);
-- 查询2023年10月的品类销售额(启用LLAP)
SET hive.execution.engine=tez;
SET hive.llap.enabled=true;
SELECT category_id, SUM(amount) AS total_sales
FROM orders
WHERE year=2023 AND month=10
GROUP BY category_id
ORDER BY total_sales DESC;
执行计划分析:
- 谓词下推(Predicate Pushdown):将
year=2023 AND month=10推到分区扫描阶段,只读取2023年10月的分区数据。 - 列修剪(Column Pruning):只读取
category_id、amount、year、month四列,减少数据传输。 - 局部聚合(Partial Aggregation):在Map阶段先计算每个
category_id的局部销售额,减少Reduce阶段的数据量。
3.2 Spark SQL:交互式OLAP的“速度担当”
(1)Spark SQL的核心原理
Spark SQL是Spark生态中的SQL引擎,基于内存计算和Catalyst优化器,支持流批一体(Structured Streaming)。其核心架构包括:
- Catalyst优化器:基于规则(Rule-Based Optimization, RBO)和成本(Cost-Based Optimization, CBO)的优化框架,负责解析、优化和生成执行计划。
- Tungsten执行引擎:采用代码生成(Code Generation)和内存管理(Off-Heap Memory),提升执行效率。
- DataFrame/Dataset API:比RDD更高级的抽象,支持类型安全和优化。
Catalyst优化器的流程:
- 解析(Parse):将SQL转化为未解析的逻辑计划(Unresolved Logical Plan)。
- 绑定(Bind):从元数据存储(如Hive metastore)获取信息,转化为解析后的逻辑计划(Resolved Logical Plan)。
- 优化(Optimize):通过RBO(如谓词下推、列修剪)和CBO(如选择join方式)优化逻辑计划,生成优化后的逻辑计划(Optimized Logical Plan)。
- 生成物理计划:将优化后的逻辑计划转化为物理计划(如SortMergeJoin、HashJoin),并选择最优的物理计划(如根据数据量选择join方式)。
- 执行(Execute):通过Tungsten引擎执行物理计划,获取结果。
Mermaid流程图:
graph TD
A[用户提交SQL/API调用] --> B[Catalyst解析生成Unresolved Logical Plan]
B --> C[绑定元数据生成Resolved Logical Plan]
C --> D[RBO/CBO优化生成Optimized Logical Plan]
D --> E[生成物理计划(如SortMergeJoin)]
E --> F[选择最优物理计划]
F --> G[Tungsten引擎执行计划]
G --> H[返回结果给用户]
(2)Spark SQL的OLAP实战:实时用户行为分析
假设我们需要分析实时用户点击流数据(来自Kafka),计算每个品类的5分钟内点击量。
步骤1:创建Spark Session
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import org.apache.spark.sql.streaming.Trigger
val spark = SparkSession.builder()
.appName("RealTimeUserBehaviorAnalysis")
.master("local[*]")
.enableHiveSupport()
.getOrCreate()
步骤2:读取Kafka流数据
val kafkaDF = spark.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "localhost:9092")
.option("subscribe", "user_clicks")
.load()
步骤3:解析JSON数据并转换为结构化数据
val clicksDF = kafkaDF.select(from_json(col("value").cast("string"), "user_id INT, product_id INT, category_id INT, click_time TIMESTAMP").as("data"))
.select("data.*")
步骤4:窗口聚合计算5分钟内的品类点击量
val windowedClicksDF = clicksDF
.withWatermark("click_time", "10 minutes") // 水印,处理迟到数据
.groupBy(
window(col("click_time"), "5 minutes"), // 5分钟窗口
col("category_id")
)
.agg(count("*").as("click_count"))
.orderBy(col("window.start").desc, col("click_count").desc)
步骤5:输出结果到控制台(或其他 sink)
val query = windowedClicksDF.writeStream
.format("console")
.trigger(Trigger.ProcessingTime("1 minute")) // 每分钟触发一次
.outputMode("complete") // 输出所有窗口的结果
.start()
query.awaitTermination()
优化说明:
- 水印(Watermark):处理迟到数据,避免窗口无限增长。
- 窗口聚合(Window Aggregation):Spark SQL会自动优化窗口聚合,将其转化为增量计算(只处理新到达的数据)。
- 代码生成(Code Generation):Tungsten引擎会将聚合操作生成原生Java代码,提升执行效率。
3.3 Presto:跨数据源OLAP的“联邦查询引擎”
(1)Presto的核心原理
Presto是一款分布式SQL查询引擎,支持跨数据源联邦查询(如Hive、MySQL、Redis、S3)。其核心架构包括:
- Coordinator:负责解析查询、生成执行计划、调度任务。
- Worker:负责执行任务(如读取数据、计算),并将结果返回给Coordinator。
- Connector:连接不同数据源的插件(如Hive Connector、MySQL Connector),负责数据读取和写入。
Presto的查询流程:
- 用户提交查询:通过CLI、JDBC或ODBC提交SQL。
- Coordinator解析查询:生成逻辑计划,然后转化为物理计划(如将查询拆分为多个Stage)。
- Coordinator调度任务:将Stage分配给Worker执行。
- Worker执行任务:通过Connector读取数据源的数据,执行计算(如过滤、聚合),并将中间结果返回给Coordinator。
- Coordinator汇总结果:将Worker返回的结果汇总,返回给用户。
Mermaid流程图:
graph TD
A[用户提交SQL] --> B[Coordinator解析生成逻辑计划]
B --> C[Coordinator生成物理计划(拆分为Stage)]
C --> D[Coordinator调度Stage到Worker]
D --> E[Worker通过Connector读取数据源数据]
E --> F[Worker执行计算(过滤、聚合)]
F --> G[Worker返回中间结果给Coordinator]
G --> H[Coordinator汇总结果]
H --> I[返回结果给用户]
(2)Presto的OLAP实战:跨Hive与MySQL的用户分析
假设我们需要分析2023年10月的用户购买行为,结合Hive中的订单数据(orders)和MySQL中的用户数据(users),计算每个国家的销售额。
步骤1:配置Presto Connector
在Presto的etc/catalog目录下创建:
hive.properties(连接Hive):connector.name=hive-hadoop2 hive.metastore.uri=thrift://localhost:9083mysql.properties(连接MySQL):connector.name=mysql connection-url=jdbc:mysql://localhost:3306/user_db connection-user=root connection-password=123456
步骤2:提交跨数据源查询
SELECT
u.country,
SUM(o.amount) AS total_sales
FROM
hive.default.orders o
JOIN
mysql.user_db.users u ON o.user_id = u.user_id
WHERE
o.year = 2023 AND o.month = 10
GROUP BY
u.country
ORDER BY
total_sales DESC;
执行流程说明:
- Coordinator:解析SQL,生成逻辑计划,然后拆分为两个Stage(Stage 1:读取Hive的
orders表和MySQL的users表;Stage 2:执行join和聚合)。 - Worker:Stage 1的Worker通过Hive Connector读取
orders表的2023年10月分区数据,通过MySQL Connector读取users表的用户数据;Stage 2的Worker执行join(根据user_id)和聚合(SUM(amount))。 - Coordinator:汇总Stage 2的结果,返回给用户。
优化说明:
- 分区修剪:Presto会自动将
o.year=2023 AND o.month=10推到Hive Connector,只读取对应的分区数据。 - 列修剪:Presto会只读取
orders表的user_id、amount、year、month列,以及users表的user_id、country列,减少数据传输。 - 并行度调整:通过
query.max-parallelism参数调整Worker的并行度(如设置为10),提升查询速度。
3.4 Kylin:预计算OLAP的“亚秒级查询引擎”
(1)Kylin的核心原理
Kylin是一款基于预计算的OLAP引擎,通过预计算Cube将复杂的查询转化为“查表”操作,支持亚秒级查询。其核心概念包括:
- 数据模型(Data Model):定义事实表和维度表的关系(如星型schema)。
- Cube定义(Cube Definition):定义Cube的维度(如时间、地区、品类)和度量(如sum(amount)、count(order_id))。
- Cube构建(Cube Build):预计算所有维度组合的度量值,存储在HBase中。
- 查询引擎(Query Engine):接收SQL查询,转化为HBase的get/scan操作,获取预计算的结果。
Kylin的Cube构建流程:
- 数据加载:从Hive中加载事实表和维度表的数据。
- 维度组合生成:根据Cube定义,生成所有可能的维度组合(如时间+地区、时间+品类、地区+品类、时间+地区+品类)。
- 预计算:对每个维度组合,计算度量值(如sum(amount))。
- 存储:将预计算的结果存储在HBase中(以维度组合作为RowKey,度量值作为列值)。
Mermaid流程图:
graph TD
A[定义数据模型(星型schema)] --> B[定义Cube(维度+度量)]
B --> C[从Hive加载事实表和维度表数据]
C --> D[生成所有维度组合]
D --> E[预计算每个维度组合的度量值]
E --> F[将结果存储在HBase中]
F --> G[接收SQL查询]
G --> H[转化为HBase的get/scan操作]
H --> I[获取预计算结果返回给用户]
(2)Kylin的OLAP实战:电商GMV统计
假设我们需要统计电商平台的GMV( Gross Merchandise Volume),按时间(年/月/日)、地区(国家/省份/城市)、品类(一级/二级/三级)维度查询,要求亚秒级响应。
步骤1:定义数据模型
在Kylin中创建数据模型,选择事实表orders和维度表time(时间)、region(地区)、product(品类)。
步骤2:定义Cube
- 维度:选择
time.year、time.month、time.day(时间维度)、region.country、region.province、region.city(地区维度)、product.category_level1、product.category_level2、product.category_level3(品类维度)。 - 度量:选择
sum(orders.amount)(GMV)、count(orders.order_id)(订单数)。 - 聚合组(Aggregation Group):将维度分为多个组,减少Cube的大小(如将时间维度和地区维度放在一个组,品类维度放在另一个组)。
步骤3:构建Cube
触发Cube构建任务,Kylin会自动完成数据加载、维度组合生成、预计算和存储。
步骤4:查询Cube
使用Kylin的SQL接口查询GMV:
SELECT
time.year,
time.month,
region.country,
product.category_level1,
SUM(orders.amount) AS gmv
FROM
kylin_cube.orders_cube
WHERE
time.year = 2023 AND time.month = 10
GROUP BY
time.year, time.month, region.country, product.category_level1
ORDER BY
gmv DESC;
执行流程说明:
- Kylin的查询引擎会解析SQL,识别出需要查询的维度(
year、month、country、category_level1)和度量(gmv)。 - 根据Cube的预计算结果,Kylin会直接从HBase中读取对应的RowKey(
2023|10|China|Electronics)的gmv列值,返回给用户。 - 由于预计算的存在,查询延迟通常在100ms以内。
四、Hadoop生态OLAP的性能优化:实战技巧
无论使用哪个OLAP组件,性能优化都是关键。以下是通用的优化技巧:
4.1 数据模型优化
- 使用星型schema:减少join次数,提升查询效率。
- 分区与分桶:
- 分区:按时间(如年/月/日)、地区等维度分区,减少数据扫描量(如Hive的
PARTITIONED BY)。 - 分桶:按高频查询的维度(如
user_id)分桶,提升join效率(如Hive的CLUSTERED BY)。
- 分区:按时间(如年/月/日)、地区等维度分区,减少数据扫描量(如Hive的
- 列式存储:使用Parquet、ORC等列式存储格式,提升读取效率(如Hive的
STORED AS PARQUET)。
4.2 查询优化
- 谓词下推(Predicate Pushdown):将过滤条件推到数据源,减少数据读取量(如Hive、Spark SQL、Presto都支持)。
- 列修剪(Column Pruning):只读取查询需要的列,减少数据传输量(如Spark SQL的
select语句只选必要的列)。 - 局部聚合(Partial Aggregation):在Map阶段先进行局部聚合,减少Reduce阶段的数据量(如Hive的
GROUP BY操作)。 - 缓存(Caching):将常用的数据集缓存到内存中,减少重复计算(如Spark SQL的
cache()方法、Hive的LLAP)。
4.3 组件-specific优化
- Hive:启用Tez执行引擎(
set hive.execution.engine=tez)、启用LLAP(set hive.llap.enabled=true)。 - Spark SQL:调整并行度(
spark.sql.shuffle.partitions=200)、启用代码生成(spark.sql.codegen.enabled=true)。 - Presto:调整Worker内存(
query.max-memory-per-node=8GB)、使用Parquet格式(hive.parquet.enabled=true)。 - Kylin:使用聚合组(Aggregation Group)减少Cube大小、启用增量构建(Incremental Build)处理新增数据。
五、实际应用场景:组件选型与落地案例
5.1 电商:实时报表与高并发查询
- 场景需求:需要实时统计GMV、订单数、用户转化率等指标,支持运营人员的高并发查询(如每分钟1000次查询)。
- 组件选型:
- 实时数据处理:使用Spark SQL(Structured Streaming)处理Kafka中的实时订单数据。
- 高并发查询:使用Kylin预计算Cube,支持亚秒级查询。
- 落地案例:某电商平台使用Kylin构建了GMV Cube,支持按时间、地区、品类的高并发查询,查询延迟从原来的10秒降低到50ms,运营人员的工作效率提升了20倍。
5.2 金融:风险分析与跨数据源查询
- 场景需求:需要分析用户的交易数据(存储在Hive)和征信数据(存储在MySQL),识别欺诈交易。
- 组件选型:
- 跨数据源查询:使用Presto联邦查询Hive和MySQL的数据。
- 批处理分析:使用Hive处理大规模的交易数据。
- 落地案例:某银行使用Presto查询Hive中的交易数据和MySQL中的征信数据,识别出1000多笔欺诈交易,挽回损失500多万元。
5.3 电信:用户行为分析与实时推荐
- 场景需求:需要分析用户的通话记录(存储在HDFS)和上网记录(存储在Kafka),实时推荐个性化服务。
- 组件选型:
- 实时数据处理:使用Spark SQL(Structured Streaming)处理Kafka中的上网记录。
- 交互式查询:使用Impala查询HDFS中的通话记录。
- 落地案例:某电信运营商使用Spark SQL处理实时上网记录,结合Impala查询历史通话记录,为用户推荐个性化的流量套餐,推荐成功率提升了15%。
六、工具与资源推荐
6.1 可视化工具
- Superset:开源的BI工具,支持Hive、Spark SQL、Presto、Kylin等组件,提供丰富的图表(如折线图、柱状图、地图)。
- Tableau:商业BI工具,支持连接Hadoop生态的OLAP组件,提供交互式可视化分析。
- Power BI:微软的BI工具,支持连接Spark SQL、Presto等组件,适合企业级用户。
6.2 监控工具
- Prometheus:开源的监控工具,支持监控Hadoop集群(如HDFS、YARN)、OLAP组件(如Spark、Presto)的性能指标(如CPU、内存、磁盘使用情况)。
- Grafana:开源的可视化监控工具,与Prometheus集成,提供实时的 dashboard(如集群负载、查询延迟)。
6.3 学习资源
- 书籍:《Hadoop权威指南》(第4版)、《Spark快速大数据分析》(第2版)、《Presto实战》。
- 课程:Coursera《Big Data Analytics with Hadoop》、Udemy《Apache Spark SQL for Data Engineers》。
- 官方文档:Hive官方文档(https://hive.apache.org/)、Spark官方文档(https://spark.apache.org/docs/latest/)、Presto官方文档(https://prestodb.io/)、Kylin官方文档(https://kylin.apache.org/)。
七、未来趋势:Hadoop生态OLAP的进化方向
7.1 实时OLAP:流批一体
随着实时数据的增长,实时OLAP成为趋势。Hadoop生态中的组件正在向“流批一体”进化:
- Spark SQL:支持Structured Streaming,处理实时数据。
- Flink SQL:基于Flink的流处理引擎,支持低延迟的实时OLAP(如毫秒级延迟)。
- Doris:支持实时数据导入(如从Kafka导入)和低延迟查询(如亚秒级)。
7.2 云原生OLAP:托管服务
随着云 computing 的普及,云原生OLAP成为主流:
- AWS Athena:基于Presto的托管OLAP服务,支持查询S3中的数据。
- Google BigQuery:基于Dremel的托管OLAP服务,支持大规模数据的交互式查询。
- Azure Synapse Analytics:微软的托管数据仓库服务,支持连接Hadoop生态的组件。
7.3 AI与OLAP的结合:智能分析
AI技术正在改变OLAP的使用方式:
- 自动查询生成:使用大语言模型(如GPT-4)生成SQL查询(如用户输入“统计2023年10月的GMV”,模型自动生成对应的SQL)。
- 智能优化:使用机器学习模型优化查询计划(如根据查询历史调整并行度、选择join方式)。
- 智能推荐:根据用户的查询行为推荐相关的分析维度(如用户查询“2023年10月的GMV”,推荐“按地区拆分”或“按品类拆分”)。
结论:Hadoop生态OLAP的核心价值
Hadoop生态的OLAP解决方案的核心价值在于**“大规模数据的高效分析”**:
- 分布式存储:HDFS支持PB级数据的存储,解决了传统数据仓库的存储瓶颈。
- 并行计算:MapReduce、Spark等计算框架支持大规模数据的并行处理,提升了分析效率。
- 生态兼容性:Hive、Spark SQL、Presto等组件支持多种数据源(如Hive、MySQL、Kafka),满足企业的多样化需求。
- 开源成本:所有组件都是开源的,降低了企业的IT成本。
随着实时数据、云原生和AI技术的发展,Hadoop生态的OLAP解决方案将继续进化,为企业提供更高效、更智能的数据分析能力。无论是数据工程师还是架构师,都需要掌握Hadoop生态的OLAP组件,才能在大数据时代立于不败之地。
参考资料
- Apache Hive官方文档:https://hive.apache.org/
- Apache Spark官方文档:https://spark.apache.org/docs/latest/
- Presto官方文档:https://prestodb.io/
- Apache Kylin官方文档:https://kylin.apache.org/
- 《Hadoop权威指南》(第4版),Tom White著
- 《Spark快速大数据分析》(第2版),Holden Karau著
(注:本文中的代码示例均为简化版,实际使用时需要根据具体环境调整配置。)
602

被折叠的 条评论
为什么被折叠?



