Apache Gluten 常用 CLI 命令与工具详解
汇总 Apache Gluten 集成后 spark-submit、spark-shell、spark-sql 的常用命令与 --conf 用法,以及 EXPLAIN、计划变更日志、日志关键字等诊断命令与性能对比方法。
Apache Gluten 常用 CLI 命令与工具详解
Gluten 不提供独立命令行,它的“CLI”就是 Spark 自带的 spark-submit、spark-shell、spark-sql 等工具,再加上一组用于查看执行计划与原生执行情况的诊断手段。本文以 Apache Gluten 1.7.0 + Spark 3.5.5 + JDK 17 为基准,给出实用命令与真实回显。
一、通用约定
1.1 环境变量
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 # CentOS 8 为 /usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH
export SPARK_HOME=/opt/spark
GLUTEN_JAR=/opt/gluten/gluten-velox-bundle-spark3.5_2.12-linux_amd64-1.7.0.jar
JVM_OPTS='--add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true'
JVM_OPTS 是 JDK 17 下的必需项,缺少会报 sun.misc.Unsafe or java.nio.DirectByteBuffer.<init>(long, int) not available。
1.2 最小 Gluten 配置组合
三个 --conf 加一个 --jars 即可启用:
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true \
--conf spark.memory.offHeap.size=1g \
--conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager \
--jars $GLUTEN_JAR
二、spark-submit
2.1 提交 Scala/Java 作业
$SPARK_HOME/bin/spark-submit --master 'local[4]' --driver-memory 512m \
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true \
--conf spark.memory.offHeap.size=1g \
--conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager \
--conf "spark.driver.extraJavaOptions=$JVM_OPTS" \
--conf "spark.executor.extraJavaOptions=$JVM_OPTS" \
--jars $GLUTEN_JAR \
--class com.example.GlutenAgg /opt/app/myapp.jar
2.2 提交 Python 作业
$SPARK_HOME/bin/spark-submit --master 'local[4]' --driver-memory 512m \
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true \
--conf spark.memory.offHeap.size=2g \
--conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager \
--jars $GLUTEN_JAR /opt/app/job.py
2.3 常用参数速查
| 参数 | 说明 |
|---|---|
--master | 集群/本地模式,如 local[4]、yarn |
--driver-memory | Driver 堆内存,示例用 512m |
--executor-memory | Executor 堆内存 |
--jars | 分发 Gluten bundle 到 Driver/Executor |
--conf | 传入任意 Spark/Gluten 配置 |
--version | 查看 Spark 版本 |
三、spark-shell
3.1 启动并验证插件
# $SPARK_HOME/bin/spark-shell --master 'local[4]' --driver-memory 512m \
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true \
--conf spark.memory.offHeap.size=1g \
--conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager \
--jars $GLUTEN_JAR
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 3.5.5
/_/
Using Scala version 2.12.18, OpenJDK 64-Bit Server VM, 17.0.20.1
scala>
在 REPL 中确认插件与内存配置:
scala> spark.conf.get("spark.plugins")
res0: String = org.apache.gluten.GlutenPlugin
scala> spark.conf.get("spark.memory.offHeap.size")
res1: String = 1g
3.2 脚本模式
把 Scala 语句写入文件后用 -i 执行(末尾 sys.exit(0) 退出):
$SPARK_HOME/bin/spark-shell --master 'local[4]' --driver-memory 512m \
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true --conf spark.memory.offHeap.size=2g \
--jars $GLUTEN_JAR -i /root/perf.scala
四、spark-sql
4.1 执行 SQL 文件
echo "SELECT count(*) AS cnt, sum(id) AS s FROM range(1000000);" > /root/test.sql
$SPARK_HOME/bin/spark-sql --master 'local[4]' --driver-memory 512m \
--conf spark.plugins=org.apache.gluten.GlutenPlugin \
--conf spark.memory.offHeap.enabled=true --conf spark.memory.offHeap.size=1g \
--conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager \
--jars $GLUTEN_JAR -f /root/test.sql
真实回显:
1000000 499999500000
4.2 执行单条语句
$SPARK_HOME/bin/spark-sql ... -e "SELECT count(*) FROM range(100)"
五、执行计划与诊断
5.1 EXPLAIN 系列
spark-sql> EXPLAIN EXTENDED SELECT count(*) AS cnt, sum(id) AS s FROM range(1000000);
spark-sql> EXPLAIN COST SELECT count(*) FROM range(1000000);
spark-sql> EXPLAIN FORMATTED SELECT count(*) FROM range(1000000);
关键点:AQE 开启时初始物理计划仍显示朴素 Spark 算子(AdaptiveSparkPlan isFinalPlan=false 下的 HashAggregate、Exchange、Range)。要直观看到原生算子,需临时关闭 AQE:
--conf spark.sql.adaptive.enabled=false
关闭后可见:
== Physical Plan ==
VeloxColumnarToRow
+- ^(2) HashAggregateTransformer(keys=[], functions=[count(1), sum(id#7L)], isStreamingAgg=false, ...)
+- ColumnarExchange SinglePartition, ENSURE_REQUIREMENTS, ... , [shuffle_writer_type=hash], ...
+- VeloxResizeBatches 1024, 2147483647, 10485760
+- ColumnarRange 0, 1000000, 1, 4, 1000000, [id#7L]
只要出现 VeloxColumnarToRow、HashAggregateTransformer、ColumnarExchange、ColumnarRange 等节点,即说明算子已被原生引擎接管。
5.2 计划变更日志
打开 Spark 的计划变更日志,观察 Gluten 的列式转换是否发生:
--conf spark.sql.planChangeLog.level=WARN \
--conf spark.sql.planChangeLog.rules=org.apache.spark.sql.execution.columnar.*
5.3 日志关键字排查
把 org.apache.gluten 日志级别设为 INFO(在 $SPARK_HOME/conf/log4j2.properties 中追加):
logger.gluten.name = org.apache.gluten
logger.gluten.level = info
启动后检索以下关键字:
| 关键字 | 含义 |
|---|---|
GlutenDriverPlugin: Gluten components | 插件已加载,列出各组件 |
SubstraitBackend: Gluten build info | 打印 Gluten/Java/Scala/Spark 版本 |
Successfully loaded library linux/amd64/libgluten.so | 原生主库加载成功 |
Successfully loaded library linux/amd64/libvelox.so | Velox 库加载成功 |
Gluten is running with Spark local mode | 本地模式下的提示 |
Gluten SQL Tab has been attached | Spark UI 已挂载 Gluten 页签 |
Excluding runtime-incompatible component: velox-iceberg | 相关依赖缺失的正常告警 |
# 在作业日志中过滤
grep -iE 'gluten|velox' /tmp/gluten_run.log
5.4 Spark UI
启用 Gluten 后,Web UI 会额外出现 “Gluten SQL” 页签,可查看原生执行相关的统计与算子树。
六、性能对比命令
6.1 计时脚本
用 spark-shell -i 跑同一查询多轮,取稳定值(去掉冷启动轮次):
spark.sparkContext.setLogLevel("ERROR")
val q2 = "SELECT count(*) AS c FROM range(8000000) a JOIN range(8000000) b ON a.id = b.id"
for (i <- 1 to 3) {
val t0 = System.nanoTime()
val r = spark.sql(q2).collect()
val t1 = System.nanoTime()
println("ITER=" + i + " ELAPSED_MS=" + ((t1 - t0) / 1000000) + " RESULT=" + r(0))
}
sys.exit(0)
分别以“带 Gluten 参数”和“不带 Gluten 参数”各跑一次,即可对比。
6.2 实测对照
环境:Spark 3.5.5 / JDK 17 / local[4] / driver 512m / offHeap 2g。
| 查询 | Gluten 开启 | Gluten 关闭 |
|---|---|---|
| Q1 字符串聚合(2000 万行) | 2105 ms | 793 ms |
| Q2 自连接聚合(800 万 × 800 万) | 1479 ms | 4348 ms |
结论:Q2 这类连接/Shuffle 密集型负载,Gluten 约快 2.9×;Q1 这类轻量字符串聚合,原生 Spark codegen 反而更快。Gluten 的收益强依赖工作负载形态,简单查询会因 JNI 与列式搬运产生额外开销。
七、命令速查表
| 目的 | 命令要点 |
|---|---|
| 查看 Spark 版本 | spark-submit --version |
| 启用 Gluten | --conf spark.plugins=org.apache.gluten.GlutenPlugin --jars $GLUTEN_JAR |
| 预留原生内存 | --conf spark.memory.offHeap.enabled=true --conf spark.memory.offHeap.size=1g |
| 列式 Shuffle | --conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager |
| 查看原生计划 | EXPLAIN EXTENDED ... + --conf spark.sql.adaptive.enabled=false |
| 计划变更日志 | --conf spark.sql.planChangeLog.level=WARN |
| 查看 Gluten 日志 | `grep -iE 'gluten |
| 性能对比 | spark-shell -i + System.nanoTime() 多轮计时 |