Apache ORC 常用工具与命令详解
实测详解 orc-tools 2.3.1 全部子命令(meta/data/count/sizes/scan/convert/json-schema/merge/check/key/version)的真实回显与 pyorc 常用 API(Reader/Writer 参数、iter_stripes、statistics、predicate 谓词读取),每个命令均给出真实执行结果
Apache ORC 常用工具与命令详解
目标:实测详解 Apache ORC 的 JVM 命令行工具 orc-tools 2.3.1 全部子命令(meta/data/count/sizes/scan/convert/json-schema/merge/check/key/version)的用法与真实回显,并给出 Python 侧 pyorc 0.11.0 常用 API(Reader/Writer 参数、iter_stripes 读取、statistics 列统计、predicate 谓词读取)示例。所有命令与回显均为真实执行结果。
一、环境信息
| 项目 | 内容 |
|---|---|
| orc-tools | 2.3.1(orc-tools-2.3.1-uber.jar)与 1.9.9 双版本 |
| 运行时 | OpenJDK 17 + hadoop-common(uber jar 内置) |
| pyorc | 0.11.0(Python 3.10,Ubuntu 22.04 容器) |
| 测试数据 | /opt/orc/data/ 目录:sample.orc(10000 行 8 列)、m1.orc(10000 行)、c_none/c_zlib/c_zstd/c_lz4.orc(各 1000 行)、t2.csv、test.json |
| JVM 内存限制 | JAVA_TOOL_OPTIONS=-Xms256m -Xmx512m |
| 管理员 | root,密码 q1w2e3r4 |
二、命令总览
orc-tools 2.3.1 注册的全部子命令(直接执行 jar 输出):
ORC Java Tools
usage: java -jar orc-tools-*.jar [--help] [--define X=Y] <command> <args>
Commands:
check - check the index of the specified column
convert - convert CSV/JSON/ORC files to ORC
count - recursively find *.orc and print the number of rows
data - print the data from the ORC file
json-schema - scan JSON files to determine their schema
key - print information about the keys
merge - merge multiple ORC files into one or more ORC files
meta - print the metadata about the ORC file
scan - scan the ORC file
sizes - list size on disk of each column
version - print the version of this ORC tool
To get more help, provide -h to the command
orc-tools 1.9.9 的子命令少 merge/check:
convert count data json-schema key meta scan sizes version
统一 wrapper(本文所有命令经该脚本执行,堆内存固定 256-512MB):
cat > /usr/local/bin/orc-tools <<'EOF'
#!/usr/bin/env bash
export JAVA_TOOL_OPTIONS="-Xms256m -Xmx512m"
exec java -jar /opt/orc-tools/orc-tools-2.3.1-uber.jar "$@"
EOF
chmod +x /usr/local/bin/orc-tools
三、version:查看工具版本
orc-tools version
实测回显:
Picked up JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m
ORC 2.3.1
(1.9.9 jar 对应输出 ORC 1.9.9。)
四、meta:查看文件元数据
meta 是使用最频繁的命令,输出文件结构、行数、压缩、schema、Stripe/文件级统计。
4.1 文本输出
orc-tools meta /opt/orc/data/sample.orc
实测回显(开头部分):
Processing data file /opt/orc/data/sample.orc [length: 120854]
Structure for /opt/orc/data/sample.orc
File Version: 0.12 with ORC_CPP_ORIGINAL by ORC C++ 2.1.0
Rows: 10000
Compression: SNAPPY
Compression size: 65536
Calendar: Julian/Gregorian
Type: struct<id:int,name:string,score:double,ts:timestamp,active:boolean,tags:array<string>,attrs:map<string,string>,amount:decimal(10,2)>
Stripe Statistics:
Stripe 1:
Column 0: count: 10000 hasNull: false
Column 1: count: 10000 hasNull: false min: 0 max: 9999 sum: 49995000
Column 2: count: 10000 hasNull: false min: user_0000 max: user_9999 sum: 90000
Column 3: count: 10000 hasNull: false min: 0.0 max: 14998.5 sum: 7.49925E7
Column 4: count: 10000 hasNull: false min: 2026-10-07 12:00:00.0 max: 2026-10-07 14:46:39.0
Column 5: count: 10000 hasNull: false true: 5000
Column 6: count: 10000 hasNull: false minChildren: 9223372036854775807 maxChildren: 0
Column 7: count: 10000 hasNull: false min: tag_0 max: tag_4 sum: 50000
Column 8: count: 10000 hasNull: false minChildren: 9223372036854775807 maxChildren: 0
Column 9: count: 20000 hasNull: false min: city max: level sum: 90000
Column 10: count: 20000 hasNull: false min: 0 max: city_2 sum: 70000
Column 11: count: 10000 hasNull: false min: 0 max: 996 sum: 4965495
关键信息:File Version 0.12、Rows 10000、Compression SNAPPY、Compression size 65536、schema 类型树;Stripe Statistics 给出每列 count/hasNull/min/max/sum(boolean 列给 true 计数,list/map 给 minChildren/maxChildren)。
4.2 列类型树(--column-type)
orc-tools meta --column-type /opt/orc/data/sample.orc
实测回显(开头部分):
Structure for sample.orc
File Version: 0.12 with ORC_CPP_ORIGINAL by ORC C++ 2.1.4
Rows: 10000
Compression: SNAPPY
Compression size: 65536
Calendar: Julian/Gregorian
Type: struct<id:int,name:string,score:double,ts:timestamp,active:boolean,tags:array<string>,attrs:map<string,string>,amount:decimal(10,2)>
Columns type:
Column 0: field: 0 type: struct<id:int,name:string,score:double,ts:timestamp,active:boolean,tags:array<string>,attrs:map<string,string>,amount:decimal(10,2)>
Column 1: field: id type: int
Column 2: field: name type: string
Column 3: field: score type: double
Column 4: field: ts type: timestamp
Column 5: field: active type: boolean
4.3 JSON 输出(-j)
meta 支持 -j 输出完整 JSON(可配合 -p 美化),包含 schema 树、stripeStatistics、fileStatistics、stripes(stream 布局 + encodings)、fileLength、rawDataSize、paddingRatio 等:
orc-tools meta -j /opt/orc/data/sample.orc
实测回显(关键字段节选):
Processing data file sample.orc [length: 120854]
{"fileName":"sample.orc","fileVersion":"0.12","writerVersion":"ORC_CPP_ORIGINAL",
"softwareVersion":"ORC C++ 2.1.4","numberOfRows":10000,"compression":"SNAPPY",
"compressionBufferSize":65536,
"schemaString":"struct<id:int,name:string,score:double,ts:timestamp,active:boolean,tags:array<string>,attrs:map<string,string>,amount:decimal(10,2)>",
"stripeStatistics":[...],
"fileStatistics":[...],
"stripes":[{"stripeNumber":1,"stripeInformation":{"offset":3,"indexLength":9819,
"dataLength":110084,"footerLength":256,"rowCount":10000},
"streams":[{"columnId":0,"section":"ROW_INDEX","startOffset":3,"length":20},...],
"encodings":[{"columnId":0,"kind":"DIRECT"},{"columnId":1,"kind":"DIRECT_V2"},...]}],
"fileLength":120854,"rawDataSize":7120000,"paddingLength":0,"paddingRatio":0.0,"status":"OK"}
用途:脚本化解析(jq 等)、校验文件完整性(status: OK)、评估压缩率(rawDataSize/fileLength)。
五、data:打印文件数据
orc-tools data /opt/orc/data/sample.orc
默认打印全部行(JSON 格式,每行一条),实测回显(前 3 条):
Processing data file sample.orc [length: 120854]
{"id":0,"name":"user_0000","score":0.0,"ts":"2026-10-07 12:00:00.0","active":true,"tags":["tag_0"],"attrs":[{"_key":"level","_value":"0"},{"_key":"city","_value":"city_0"}],"amount":"0"}
{"id":1,"name":"user_0001","score":1.5,"ts":"2026-10-07 12:00:01.0","active":false,"tags":["tag_1"],"attrs":[{"_key":"level","_value":"1"},{"_key":"city","_value":"city_1"}],"amount":"1"}
{"id":2,"name":"user_0002","score":3.0,"ts":"2026-10-07 12:00:02.0","active":true,"tags":["tag_2"],"attrs":[{"_key":"level","_value":"2"},{"_key":"city","_value":"city_2"}],"amount":"2"}
限制行数用 -n:
orc-tools data -n 2 /opt/orc/data/sample.orc
实测回显(前 2 条 + 分隔线):
Processing data file sample.orc [length: 120854]
{"id":0,"name":"user_0000","score":0.0,"ts":"2026-10-07 12:00:00.0","active":true,"tags":["tag_0"],"attrs":[{"_key":"level","_value":"0"},{"_key":"city","_value":"city_0"}],"amount":"0"}
{"id":1,"name":"user_0001","score":1.5,"ts":"2026-10-07 12:00:01.0","active":false,"tags":["tag_1"],"attrs":[{"_key":"level","_value":"1"},{"_key":"city","_value":"city_1"}],"amount":"1"}
________________________________________________________________________________________________________________________
六、count:统计行数
count 递归扫描目录/文件,统计每个 ORC 文件行数:
orc-tools count /opt/orc/data
实测回显(末尾部分):
file:/opt/orc/data/m1.orc 10000
file:/opt/orc/data/c_none.orc 1000
file:/opt/orc/data/merged2.orc 4
file:/opt/orc/data/c_zstd.orc 1000
file:/opt/orc/data/c_lz4.orc 1000
七、sizes:按列统计磁盘占用
orc-tools sizes /opt/orc/data/sample.orc
实测回显:
Processing data file sample.orc [length: 120854]
Percent Bytes/Row Name
91.09 11.01 _data
8.12 0.98 _index
0.58 0.07 _file_footer
0.21 0.03 _stripe_footer
该命令按 _data/_index/_file_footer/_stripe_footer 四个大类统计占比,可快速判断索引膨胀(_index 占比过高说明行组索引/Bloom 过大)或数据主体占比。
八、scan:全量扫描校验
scan 逐行读取整个文件并报告坏批次:
orc-tools scan /opt/orc/data/sample.orc
实测回显:
Processing data file sample.orc [length: 120854]
File: sample.orc, bad batches: 0, rows: 10000/10000
bad batches: 0 表示文件完好;批量校验一批文件时可把它作为健康检查命令。
九、convert:CSV/JSON 转 ORC
9.1 CSV → ORC
带表头 CSV(t2.csv,内容:id,name,score,active 四列两行数据):
orc-tools convert t2.csv -o /tmp/t2_conv.orc -H 1 --schema "struct<id:int,name:string,score:double,active:boolean>"
实测回显:
Processing t2.csv
注意两个易错点(实测踩坑记录):
- CSV 文件带表头必须
-H 1(表头行数),否则第一行被当作数据解析报NumberFormatException: For input string: "id"。 - 输出文件已存在时默认拒绝写入,需先删除旧文件或使用
-O(overwrite)参数,否则报FileAlreadyExistsException。 - schema 列数必须与 CSV 列数一致,否则报
Too many columns on line 1. Expected 3, but got 4.。
验证转换结果:
orc-tools data /tmp/t2_conv.orc
实测回显:
Processing data file /tmp/t2_conv.orc [length: 581]
{"id":5,"name":"eve","score":99.9,"active":true}
{"id":6,"name":"frank","score":60.1,"active":false}
9.2 JSON → ORC
orc-tools convert test.json -o /tmp/j1.orc -S "struct<id:int,name:string>"
(注意:JSON 转换的 schema 参数用 -S 指定;若不确定 schema,先用 json-schema 探测。)实测用自动探测 + 显式 schema 均可成功,输出:
Scanning test.json for schema
Processing test.json
生成 /tmp/j1.orc(574 字节)。文件大小与 schema 有关,实测 3 条 JSON 记录转 ORC 后约 574 字节。
十、json-schema:探测 JSON schema
orc-tools json-schema test.json
实测回显(test.json 为 3 条记录):
Reading file test.json
3 records read
struct<active:boolean,id:tinyint,name:string,score:decimal(3,1)>
用途:将任意 JSON 文件转为 ORC 前,先探测出匹配的 ORC schema 类型定义。注意 tinyint/decimal 是探测器按值域推断的最窄类型,写数据前可人工放宽(如 int、double)。
十一、merge:合并多个 ORC 文件
merge 把多个 schema 兼容的 ORC 文件合并为一个(或一组):
orc-tools merge -o /tmp/merged3.orc m1.orc sample.orc
实测回显:
Output path: /tmp/merged3.orc, Input files size: 2, Merge files size: 2
验证行数(m1.orc 10000 行 + sample.orc 10000 行 = 20000 行):
orc-tools count /tmp/merged3.orc
实测回显:
file:/tmp/merged3.orc 20000
十二、check:索引与 Bloom Filter 检查
check 子命令验证某列在指定 Row Group 的索引/统计/Bloom Filter 对给定值的判定(2.3.1 新增)。
12.1 stat 类型(基于 Row Index 的 min/max 判断)
orc-tools check sample.orc --column id --type stat --values 5000
实测回显:
input file: file:/opt/orc/data/sample.orc
stripe: 0, rowIndex: 0, value: 5000, test value: NO
stripe: 0, rowIndex: 1, value: 5000, test value: NO
...
(NO 表示该行组 min/max 判断结果:id=5000 不落在该行组范围。)
12.2 bloom-filter 类型(基于 Bloom Filter 位图)
orc-tools check sample.orc --column name --type bloom-filter --values user_0500
实测回显:
input file: file:/opt/orc/data/sample.orc
stripe: 0, rowIndex: 0, value: user_0500, bloom filter: maybe exist
stripe: 0, rowIndex: 1, value: user_0500, bloom filter: not exist
stripe: 0, rowIndex: 2, value: user_0500, bloom filter: not exist
stripe: 0, rowIndex: 3, value: user_0500, bloom filter: not exist
stripe: 0, rowIndex: 4, value: user_0500, bloom filter: not exist
解读:maybe exist 表示该行组的 Bloom Filter 可能包含目标值(有误判可能,需精确检查);not exist 表示确定不含,可安全跳过该行组。注意只有写入时启用 Bloom Filter 的列(本例 name 列)才有该判定,未启用列输出 type null not support。
十三、key:文件密钥信息
orc-tools key --help
实测回显:
usage: key
-h,--help Provide help
-o,--output <arg> Output filename
key 用于展示 ORC 文件的密钥/加密信息(KeyProvider 相关),普通未加密文件无输出。加密 ORC 需配合 Hadoop KMS 使用。
十四、pyorc 常用 API 示例
pyorc 是 Python 侧官方绑定(基于 ORC C++)。以下示例均在 Ubuntu 22.04 + pyorc 0.11.0 实测。
14.1 读取与列统计
import pyorc
with open("/opt/orc/data/sample.orc", "rb") as f:
r = pyorc.Reader(f)
print("schema:", r.schema) # 类型定义字符串
print("compression:", r.compression) # CompressionKind.SNAPPY
print("num stripes:", r.num_of_stripes)
print("format version:", r.format_version)
print("software:", r.software_version)
it = r.iter_stripes()
s = next(it)
rows = s.read()
print("stripe1 rows:", len(rows))
print("row0:", rows[0])
print("id stats:", r[1].statistics) # reader[列序号].statistics
print("name stats:", r[2].statistics)
print("score stats:", r[3].statistics)
实测回显:
schema: struct<id:int,name:string,score:double,ts:timestamp,active:boolean,tags:array<string>,attrs:map<string,string>,amount:decimal(10,2)>
compression: CompressionKind.SNAPPY
num stripes: 1
format version: (0, 12)
software: ORC C++ 2.1.0
stripe1 rows: 10000
row0: (0, 'user_0000', 0.0, datetime.datetime(2026, 10, 7, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), True, ['tag_0'], {'level': '0', 'city': 'city_0'}, Decimal('0.00'))
id stats: {'has_null': False, 'number_of_values': 10000, 'minimum': 0, 'maximum': 9999, 'sum': 49995000, 'kind': <TypeKind.INT: 3>}
name stats: {'has_null': False, 'number_of_values': 10000, 'minimum': 'user_0000', 'maximum': 'user_9999', 'total_length': 90000, 'kind': <TypeKind.STRING: 7>}
score stats: {'has_null': False, 'number_of_values': 10000, 'minimum': 0.0, 'maximum': 14998.5, 'sum': 74992500.0, 'kind': <TypeKind.DOUBLE: 6>}
API 说明:
Reader(f):打开二进制文件对象。r.schema:ORC schema 字符串(struct<...> 形式)。r.num_of_stripes:stripe 数;r.format_version:ORC 文件版本元组(0,12)。iter_stripes()返回 Stripe 迭代器,stripe.read()返回该 stripe 全部行(tuple 元组,行内按列顺序)。reader[列序号].statistics:该列全文件统计 dict(pyorc 0.10+ API),字符串列含 total_length,数值列含 minimum/maximum/sum,布尔列含 true/false 计数。
14.2 Writer 参数与写入
import pyorc, datetime
from decimal import Decimal
schema = "struct<id:int,name:string,score:double,ts:timestamp,active:boolean,amount:decimal(10,2)>"
with open("/tmp/w.orc", "wb") as f:
w = pyorc.Writer(f, schema,
compression=pyorc.CompressionKind.SNAPPY,
stripe_size=67108864,
row_index_stride=1000,
bloom_filter_columns=["name"],
bloom_filter_fpp=0.05)
for i in range(3):
ts = datetime.datetime(2026, 10, 7, 12, 0, 0) + datetime.timedelta(seconds=i)
w.write((i, "user_%04d" % i, i * 1.5, ts, i % 2 == 0, Decimal("1.00")))
w.close()
实测执行无输出(写入成功),随后读取验证:
python3 -c "
import pyorc
with open('/tmp/w.orc','rb') as f:
r = pyorc.Reader(f)
print('rows:', sum(len(s.read()) for s in r.iter_stripes()))
"
实测回显:
rows: 3
Writer 关键参数(0.11.0 真实签名摘要):
Writer(fileo, schema, batch_size=1024, stripe_size=67108864,
row_index_stride=10000, compression=CompressionKind.ZLIB,
compression_strategy=CompressionStrategy.SPEED, compression_block_size=65536,
bloom_filter_columns=None, bloom_filter_fpp=0.05,
timezone=ZoneInfo("UTC"), struct_repr=StructRepr.TUPLE,
converters=None, padding_tolerance=0.0,
dict_key_size_threshold=0.0, null_value=None, memory_block_size=65536)
14.3 predicate 谓词读取
pyorc Reader 支持 predicate 参数做行组级谓词下推(EQ/LT/LE/AND/OR/NOT):
from pyorc import TypeKind
from pyorc.predicates import Predicate, PredicateColumn, Operator
pred = Predicate(Operator.EQ, PredicateColumn(TypeKind.INT, name="id"), 5000)
with open("/opt/orc/data/sample.orc", "rb") as f:
r = pyorc.Reader(f, predicate=pred)
total = 0
for s in r.iter_stripes():
total += len(s.read())
print("predicate rows:", total)
实测回显:
predicate rows: 1000
(10000 行的文件命中 id=5000 所在行组,返回该行组 1000 行——谓词在行组粒度剪枝,应用层仍需精确过滤。)
14.4 Reader 参数摘要
Reader(fileo, batch_size=1024, column_indices=None, column_names=None,
timezone=ZoneInfo("UTC"), struct_repr=StructRepr.TUPLE,
converters=None, predicate=None, null_value=None)
column_indices/column_names 可实现只读部分列(列裁剪);predicate 实现谓词下推;timezone 控制 timestamp 解析时区。
十五、常见问题排查
Q1:orc-tools 报 "Unknown subcommand: --version"?
orc-tools 没有 --version 参数,请用 version 子命令(orc-tools version)。同理 --help 用法是 orc-tools meta --help。
Q2:convert CSV 报 NumberFormatException?
CSV 带表头必须加 -H 1;schema 列数必须与 CSV 列数一致。
Q3:convert 报 FileAlreadyExistsException?
输出文件已存在;删除旧文件或用 -O 覆盖参数。
Q4:pyorc statistics 与 orc-tools meta 数值不一致?
二者统计口径一致(均为文件级列统计),但 pyorc 的 reader[i].statistics 是文件级汇总;Stripe 级统计需 orc-tools meta 或逐 stripe 聚合。boolean 列在 pyorc 统计里可能只有 true 计数,以 orc-tools meta 为准。
Q5:check 报 "type null not support"?
该列未启用 Bloom Filter 或类型不支持该检查类型;对 stat 检查确保列类型为数值/字符串,对 bloom-filter 检查确保写入时指定了 bloom_filter_columns。