这是一个非常重要且高性能的数据存储格式,对于大数据处理来说,理解 ORC 是至关重要的。
一、ORC 是什么?
ORC,全称为 Optimized Row Columnar,即“优化的行列式”存储格式。
- 它不是数据库:而是一种专门为 Hadoop 生态系统设计的、用于高效存储和处理大量数据的文件格式。
- 它是列式存储:与传统的按行存储(如 CSV、文本文件)不同,ORC 将数据按列而不是按行进行存储。这是其高性能的核心所在。
- 它是优化的:它在早期的 RC(Record Columnar)文件格式基础上进行了大量优化,提供了更好的压缩和读写性能。
你可以把它想象成大数据领域的“高度压缩且带有索引的 Excel 表格”,但数据是按列存放的。
二、为什么需要 ORC?列式存储的优势
假设你有一张巨大的表,有 100 亿行数据,包含 user_id, name, age, city, purchase_amount 等字段。
现在要执行一个查询:SELECT AVG(purchase_amount) FROM sales WHERE city = 'Beijing';
1. 行式存储(如 TextFile)的做法:
数据库必须逐行读取每一行数据(所有列),然后检查 city 字段是否为 ‘Beijing’,如果是,再取出 purchase_amount 字段。它会读取大量不相关的数据(如 user_id, name, age),导致 I/O 效率极低。
2. 列式存储(ORC)的做法:
- 数据在磁盘上是这样组织的:所有
user_id的值存储在一起,所有city的值存储在一起,所有purchase_amount的值也存储在一起。 - 执行上述查询时,Hive 只需要:
- 只读取
city这一列:快速扫描这一列,找到所有值为 ‘Beijing’ 的位置(行索引)。 - 只读取
purchase_amount这一列:根据上一步找到的位置,直接去purchase_amount列的对应位置取出数值进行计算。
- 只读取
- 优势立即显现:
- 极高的 I/O 效率:避免了读取不必要的列,大大减少了磁盘 I/O 数据量。
- 出色的压缩率:同一列的数据类型相同,重复值多(例如
city列会有大量重复城市名),列式存储更利于使用高效的压缩算法(如 Run-length Encoding,字典编码),显著减少存储空间。 - 向量化处理:列式数据布局非常适合现代 CPU 的向量化计算指令,可以一次性处理一批数据,而不是一次一个值,极大地提高了计算性能。
三、ORC 的核心结构与高级特性
ORC 文件不仅仅是简单地把列数据堆在一起,它内部包含了许多“元数据”和“索引”,使其异常强大。
一个 ORC 文件由以下部分组成:
1. Stripe(条带)
- 这是 ORC 文件的主体数据块,相当于一个“数据单元”。
- 通常每个 Stripe 的大小为 256MB。
- 每个 Stripe 内部包含多行的数据,并且每个列的数据在 Stripe 内是独立存储的。
- 这使得读取操作可以在一个 Stripe 内高效地进行。
2. File Footer(文件脚注)
- 这是文件的“目录”,包含至关重要的元信息:
- Stripes 列表:文件中每个 Stripe 的信息(如行数、位置等)。
- Schema 信息:表的结构(列名、数据类型)。
- 统计信息(Statistics):这是 ORC 的王牌特性——谓词下推(Predicate Pushdown) 的基础。
- 每个 Stripe 的每一列,都存储了其最小值、最大值、计数、求和等聚合信息。
- 在执行
WHERE city = 'Beijing'时,Hive 可以先检查每个 Stripe 的city列的统计信息。如果一个 Stripe 的max(city)是 ‘Shanghai’ 而min(city)是 ‘Guangzhou’,那么这个 Stripe 里根本不可能有 ‘Beijing’,Hive 就会跳过整个 Stripe 的读取! - 这极大地减少了需要扫描的数据量,提升了查询速度。
3. Postscript(后记)
- 位于文件末尾,记录了文件本身的元数据,如压缩格式(ZLIB, SNAPPY, NONE)、压缩参数、文件脚注的长度等。
4. Index Data(索引数据)
- 在 Stripe 级别,还包含了行级索引(Row Index),为 Stripe 中的每一万行左右记录一次偏移量, enabling more precise seeking within a stripe.
四、如何在 Hive 中使用 ORC?
1. 创建 ORC 表
-- 创建一个内部表,存储格式为 ORC
CREATE TABLE my_orc_table (
user_id INT,
name STRING,
age INT,
city STRING
) STORED AS ORC;
-- 创建表时可以指定压缩算法(例如使用 Snappy 压缩)
CREATE TABLE my_compressed_orc_table (
...
) STORED AS ORC
TBLPROPERTIES ("orc.compress"="SNAPPY"); -- 可选值:NONE, ZLIB, SNAPPY
2. 从其他表插入数据到 ORC 表
这是最常见的将文本数据转换为 ORC 格式的方式。
INSERT OVERWRITE TABLE my_orc_table
SELECT * FROM my_source_text_table;
3. 查询 ORC 表
查询方式与任何其他 Hive 表完全一样,但速度会快得多,尤其是聚合查询和带条件的查询。
SELECT city, AVG(age) FROM my_orc_table WHERE age > 20 GROUP BY city;
Hive 会自动利用 ORC 的统计信息和列式存储特性来优化这个查询。
五、优点总结
- 查询性能快:基于列式存储、谓词下推和统计信息,大大减少了磁盘 I/O。
- 压缩率高:节省大量存储空间(通常比文本格式节省 70%-90% 的空间)。
- 支持复杂类型:完美支持 Hive 的复杂数据类型(Array, Map, Struct)。
- 事务支持:ORC 是 Hive 实现 ACID 事务的基础文件格式。
- 内置索引:包含文件级和 Stripe 级的统计信息,用于加速查询。
六、缺点与注意事项
- 不适合单行频繁更新:ORC 是为大规模数据分析(OLAP)设计的,不适合频繁的单行写入、更新(OLTP)场景。写入成本较高。
- 不适合小数据量:由于其结构开销(Footers, Indexes),存储非常小的数据时可能不如文本格式高效。
- 非人类可读:无法直接用文本编辑器查看内容,必须通过 Hive、Spark、Presto 等工具查询。
七、与其他格式对比
| 格式 | 存储方式 | 压缩率 | 查询性能 | 可读性 | 适用场景 |
|---|---|---|---|---|---|
| TextFile/CSV | 行式 | 低 | 慢 | 高 | 数据交换,初始数据加载,小数据量 |
| SequenceFile | 行式 | 中 | 中 | 低 | 中间存储,二进制键值对数据 |
| RCFile | 列式 | 高 | 较快 | 低 | ORC 的前身,现已较少使用 |
| ORC | 列式 | 非常高 | 非常快(Hive最佳) | 低 | Hive 数据仓库的主力存储格式 |
| Parquet | 列式 | 非常高 | 非常快(Spark最佳) | 低 | Spark 生态的主力存储格式,跨生态系统支持更好 |
ORC vs Parquet:两者都是优秀的列式存储格式。ORC 与 Hive 的集成更紧密、优化更深(尤其是谓词下推和事务支持),而 Parquet 的设计更通用,被 Spark、Impala、Presto 等众多引擎广泛支持。选择通常取决于你的主要计算引擎。
结论
ORC 是 Hive 中高性能数据存储的事实标准。 对于任何使用 Hive 构建数据仓库的场景,都强烈建议将原始文本数据转换为 ORC(或 Parquet)格式,这将为你带来巨大的存储节省和查询性能提升,是数仓优化中最具性价比的操作之一。

1477

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



