QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

数据库内核杂谈(三十一)- 大数据时代的存储格式 -Parquet(2)

  • 2023-05-04
    北京
  • 本文字数:3012 字

    阅读完需:约 10 分钟

数据库内核杂谈(三十一)- 大数据时代的存储格式-Parquet(2)

欢迎阅读新一期的数据库内核杂谈。上一期杂谈介绍了 Parquet 存储格式。这一期,咱们收个尾,介绍一下 Parquet 如何支持表结构的演进(schema evolution)以及使用 Parquet 时的一些最佳实践。

支持 schema evolution(add/delete/rename columns)


在大数据业务驱动下,数据的表结构(table schema)会因为需求快速迭代而被改变。大数据系统需要具备在不影响现有应用程序或工作流的情况下,支持表结构演进(schema evolution)的能力。Parquet 格式为 schema evolution 提供了良好的功能支持,使其成为现代大数据系统的理想存储格式。

 

首先,Parquet 的 datafile 存储了数据的 schema information;这个信息以元数据的形式存储在数据文件中,见下图(源于上一期的实操数据)。但是,这个 schema 信息,并不是作为查询引擎的 source of truth,只是定义了这个数据文件存储的 schema(相当于这个 datafile 的 source of truth)。这个信息用来对于数据读取做优化以及确保查询引擎可以正确地解析数据。


(Parquet datafile 中存储了 schema 信息)


表格式的 source of truth 通常存储在大数据系统的元数据中心(比如 Hive Metastore,或者是 Apache Spark Catalog)。元数据中心会记录 schema 的改变,比如新增或者删除 column。同时也会保存 schema 的所有历史 version。

 

我们通过一个例子(接着使用 student 表),来看 Parquet 的 schema 信息,结合数据系统的 metadata service 是如何支持 schema evolution 的。表 student 的初始 schema 定义如下:


Table student(bigint id, string name, int age, string country, string home_address)
复制代码

 

在某个时间点,schema 改成了如下:


Table student(bigint id, string name, int age, string country, string school_name optional)
复制代码

(添加了一个新的 optional 的 field school_name,同时,为了保护隐私,删除了 home_address)。系统在改变 schema 后,新导入(插入)的数据,都用了最新的 schema。即,新的 Parquet datafile 只有 id, name, age, country 和 school_name 这些 columns,但旧的 datafile 有 id,name,age,country 和 home_address 这些 columns。

 

此时,用户对数据进行查询时,查询引擎会根据数据系统的 metastore 中存储的 schema 信息,结合读取的 Parquet datafile 上的 schema 信息,来决定如何正确地读取数据:1)当读取最新 Parquet datafile 的时候,因为 schema 是匹配的,没有任何问题。2)但读取旧 Parquet datafile 的时候,查询引擎会发现 home_address 这个 column 在新的 schema 已经被删除了。因此,没有必要读取这个 column 的数据(归功于 Parquet 的列存设计,可以避免这一块数据的 IO);同时,查询引擎发现旧 datafile 并不存在 school_name 这个 column,查询引擎可以直接返回 NULL 值或者是 default 值。3)同理可得,当我们使用一个旧的 schema 去读取数据的时候(这种情况比较少,比如 time-travel query),对于新 schema 的 column mismatch 也可以通过相同的方法来返回数据(对于已经删除的 column,返回 NULL 值或者 default 值;对于新增的 column,不用读取这部分数据)。

 

虽然 Parquet 本身不支持 rename column 操作(因为 Parquet 的 datafile 只存储了当前数据 schema 信息),但是配合 metadata service 的 schema versioning,依然可以通过新旧 column 的 mapping 信息来支持 rename column 后的数据读取。对于 column 的 type change,查询引擎配合新旧 type 的 compatibility,就可以支持数据的读取,比如 int -> bigint 等(可能会因为数据转换导致精度缺失)。

最佳实践


Devils in the detail,Parquet 有很多可配置的使用选项。合理、正确的配置才能做到在查询性能、存储优化上获得收益和平衡。在本节中,我们讨论使用 Parquet 的一些需要关注的点和相应的最佳实践。

 

压缩算法(compression)和编码选项(encoding)


Parquet 支持多种压缩和编码算法,来优化存储和查询性能。选择合适的组合对于实现最佳效果至关重要。下面是一些最佳实践:

 

压缩:Parquet 支持几乎所有流行的压缩算法,包括 Snappy、Gzip 和 LZO。Snappy 在压缩比和速度之间提供了良好的平衡,使其成为常见的选择。Gzip 提供更好的压缩比,但以较慢的压缩和解压速度作为代价。LZO 优化了速度,但提供了较低的压缩比。高度压缩的数据可能需要更多的 CPU 资源来进行解压缩,影响查询性能。所以,根据具体的业务需求(是追求查询性能还是追求存储成本)选择一个平衡的压缩算法和压缩级别。

 

编码:Parquet 支持多种编码方案,如 dict encoding, run-length encoding(RLE)和位打包(bit packing)。编码的选择取决于数据特征。例如,对于基数较低(不同值较少)的列,字典编码效果很好,而对于单调递增或递减值的列,增量编码更为合适。在绝大部分情况下,让 Parquet 自行选择就好,Parquet 会根据 column 的数据类型和分布自动选择最高效的编码技术。

数据文件大小和分区


优化文件大小和合理的分区策略可以显著地提高查询性能。

 

文件大小:将文件大小控制在 64MB 到 1GB 之间。较大的文件可以实现更好的压缩,减少管理众多小文件的开销,提高查询性能。然而,非常大的文件可能会导致内存使用增加和处理速度变慢。最佳实践就是,根据实际的查询逻辑,尝试配置不同文件大小,以找到平衡点。

 

分区:分区策略并不只适用于 Parquet。根据经常用作查询过滤器的列对数据进行分区。这允许查询引擎仅读取相关的分区,减少 I/O 开销并提高查询性能。常见的分区策略包括按日期或分类变量进行分区。避免创建太多小分区,因为这可能导致管理元数据的开销增加。


避免创建过多小文件,因为这可能对查询性能产生负面影响。

Schema evolution 支持


在第一节中,我们介绍了 Parquet 如何支持 schema evolution。下面是一些相关的最佳实践:

 

添加新 column:在添加新 column 时,尽量将其设为可选,并提供默认值。这确保了向后兼容性,因为查询引擎可以为旧数据中的新 column 返回空值或默认值。

 

重命名 column:由于 Parquet 不直接支持 column 重命名,所以需要和支持重命名的数据系统引擎联动。最佳实践就是规范命名,尽可能避免重命名。

 

更改列数据类型:将数据类型更改限制为扩展数字类型或将可为空类型更改为不可为空类型。对于更复杂的更改,使用查询引擎在查询进行时(runtime)执行类型转换。

分析型查询优化工作


过滤和排序:利用 Parquet 的谓词下推(predicate push down)和列剪裁(column prune)功能来优化查询性能。将过滤器下推到存储层可减少从磁盘读取的数据量,而列剪裁可确保只读取相关列。

 

向量化查询处理:使用支持向量化查询的查询引擎(如 Apache Arrow),以进一步提高列式数据的查询性能。

总结


这一期,咱们对 Parquet 存储格式的内容进行了收尾,聊了一下 Parquet 是如何配合大数据系统做 schema evolution 的,以及一些实际使用中的最佳实践。

写在 5 周年之际


数据库内核杂谈,最开始是在简书开始连载的(附上了第一篇的截图)。也算是一个阴差阳错的契机吧(说起来都物是人非啦。哈哈哈!)不知不觉,已经快 5 周年了!感谢大家的陪伴和支持!也感谢一下自己的坚持。周期性的更新杂谈也是反向 push 我不断去学习。期待下一个 5 年。

 

 

内核杂谈微信群和知识星球


内核杂谈有个微信群,大家会在上面讨论数据库相关话题。目前群人数快 400 人啦,所以已经不能分享群名片加入了,可以添加我的微信(zhongxiangu)或者是内核杂谈编辑的微信(wyp_34358),备注:内核杂谈。

 

除了数据库内核的专题 blog,我还会 push 自己分享每天看到的有趣的 IT 新闻,放在我的知识星球里(免费的,为爱发电),欢迎加入。



2023-05-04 23:114909

评论 1 条评论

发布
用户头像
"在绝大部分情况下,让 Parquet 自行选择就好,Parquet 会根据 column 的数据类型和分布自动选择最高效的编码技术。"官方在哪里有介绍到呢?rust的parquet的库没有这种特性吧https://github.com/jorgecarleitao/parquet2
2023-05-07 00:17 · 北京
回复
没有更多了
发现更多内容

SpringCloud 中 Zuul 网关原理及其配置

做梦都在改BUG

Java Spring Cloud 网关 Zuul

国内一流地方金融控股集团-长投控股怎样建设财务共享平台?

用友BIP

财务共享

业务高速增长,如祺出行如何用腾讯云消息队列 RocketMQ 应对挑战

科技热闻

架构训练营模块二作业

Geek_3d7c4d

NGINX Service Mesh 中的 mTLS 架构

NGINX开源社区

nginx Service Mesh

解读与用户一起“跳动”的开源实时监控工具 HertzBeat

华为云开发者联盟

后端 开发 华为云 华为云开发者联盟 企业号 5 月 PK 榜

代码级质量技术之基本框架介绍

百度Geek说

单元测试 开发语言 C++ 企业号 5 月 PK 榜

伊利与腾讯云 CODING 的「水乳交融」启示录

CODING DevOps

DevOps 最佳实践 数字化转型 CODING

MaxCompute 物化视图智能推荐最佳实践

阿里云大数据AI技术

大数据 算力加速 智能推荐 企业号 5 月 PK 榜

神笔马良看了都鼓掌

百度Geek说

人工智能 AIGC 企业号 5 月 PK 榜

复盘的价值是什么?

老张

复盘 复盘归因

借生态力量助力人工智能发展 英特尔这些年做了哪些事?

E科讯

DB-GPT: Github 两周2.6k star 数据库领域的GPT来了~

csunny

GPT autogpt LLMs

OIDC & OAuth2.0 协议及其授权模式详解|认证协议最佳实践系列【1】

Authing

身份认证 OAuth 2.0 单点登录 OIDC

央企财务共享建设路径四大趋势洞察

用友BIP

财务共享

自动驾驶研发解决方案,百度智能云市场份额第一!

Baidu AICLOUD

自动驾驶 AI 大底座

PAG动效框架源码笔记 (四)渲染框架

olinone

ios android 动画 移动 特效

JWT真的安全吗?如何解决该问题

做梦都在改BUG

JWT

Java高并发难题一网打尽,全网最全的高并发设计文档

做梦都在改BUG

Java 架构 系统设计 高并发

软件测试/测试开发丨Web自动化测试-高级定位CSS

测试人

CSS 程序员 软件测试 自动化测试 测试开发

“源生无限,同行致远”,加速迈向智能世界

说山水

公用事业财务共享如何建,看南京水务立标杆

用友BIP

财务共享

网络性能问题排查思路

蓝胖子的编程梦

TCP 网络 问题排查 问题定位 问题解析

平行云X火山引擎:探索XR观展的极致体验

火山引擎边缘云

XR 火山引擎 实时云渲染 平行云 火山引擎边缘云

全球化财务如何通过全球核算助力跨国业务的稳定增长和持续发展?

用友BIP

中企出海 全球化财务

ShareSDK Android端合规指南

MobTech袤博科技

2022 Kube-OVN开源社区年度报告

York

开源 云原生 k8s 容器网络 cni

强!PCB“金手指”从设计到生产全流程

华秋PCB

工具 PCB 连接器 PCB设计 金手指

优秀的屏幕取色软件:ColorSnapper2激活版

真大的脸盆

Mac Mac 软件 屏幕取色器

淬体归元,运营商资源域元数据管理

鲸品堂

大数据 管理 元数据 企业号 5 月 PK 榜

融云参编中国信通院「办公即时通信研究报告」,并入选「典型行业案例」

融云 RongCloud

PaaS 即时通讯 办公 信息 融云

数据库内核杂谈(三十一)- 大数据时代的存储格式-Parquet(2)_大数据_顾仲贤_InfoQ精选文章