您当前的位置:首页 > 电脑百科 > 站长技术 > 服务器

Apache Iceberg 中引入索引提升查询性能

时间:2023-05-23 11:50:59  来源:  作者:火山引擎EMR团队
本文将讨论火山引擎EMR团队针对 Iceberg 组件的优化思路,通过引入索引来提高查询性能。

Apache Iceberg 是一种开源数据 Lakehouse 表格式,提供强大的功能和开放的生态系统,如:Time travel,ACID 事务,partition evolution,schema evolution 等功能。

本文将讨论火山引擎EMR团队针对 Iceberg 组件的优化思路,通过引入索引来提高查询性能。

采用 Iceberg 构建数据湖仓

火山引擎 E-MapReduce(简称 EMR)是火山引擎数智平台(VeDI)旗下的云原生开源大数据平台产品, 提供了企业级的 Hadoop、Spark、Flink、Hive、Presto、Kafka、StarRocks、Doris、Hudi、Iceberg 等大数据生态组件,100% 开源兼容,可以帮助企业快速构建企业级大数据平台,降低运维门槛。秉承业界领先的 EMR Stateless 理念,火山引擎 EMR 可以实现集群级别的弹性伸缩,即无业务需求时释放集群,有业务需求时再拉起集群,配合智能化的冷热数据分层存储能力,助力企业在大数据基建领域进一步降本提效。

基于火山引擎 EMR 产品,可以构建数据湖仓、近实时数仓、实时数仓等场景。例如,使用 Iceberg 构建数据湖仓,从 ODS 到 DWD 等不同的分层进行建模,将数据 HFDS 或 TOS(火山引擎对象存储产品)上,然后采用 Trino 或者 Spark 去做分析。

 

图片

 

如何加速查询性能,使其尽可能接近专门的分布式数仓(如 ClickHouse 等),是需要思考和探究的问题。

索引是业界常用的提高查询性能的手段之一,针对 Iceberg 我们也采用了增加索引的方式。对常用的列字段构建 Index,在进行 table scan 时利用 Index 只返回匹配的数据,降低匹配数据量,从而大大提高查询性能。

Iceberg 介绍

介绍 Iceberg Index 功能之前,我们先简单介绍下 Iceberg 的架构。Iceberg 具有分层的元数据架构,如下如所示。

 

图片

 

Spark、Presto、Flink 等多种引擎读取 Iceberg 的数据,就是利用分层的元数据找到 data file 列表。例如,Spark 引擎解析 SQL 语句,然后调用 Iceberg 的接口,获取 data file 并进行 task 切分。

 

图片

 

在 Manifest file 中记录了 data file 中字段的最大值和最小值。

"data_file": {
        "content": 0,
        "file_path": "hdfs://emr-cluster/warehouse/hive/db.db/sample/data/ts_day=2020-12-31/category=diamond/00000-0-220aa9a6-4530-499f-9450-da946d667624-00001.parquet",
        "file_format": "PARQUET",
        ......
        "lower_bounds": {
                "array": [{
                        "key": 1,
                        "value": "u0006u0000u0000u0000"
                }, {
                        "key": 2,
                        "value": "diamond"
                }, {
                        "key": 3,
                        "value": "u0000u0004܍ŷu0005u0000"
                }]
        },
        "upper_bounds": {
                "array": [{
                        "key": 1,
                        "value": "u0007u0000u0000u0000"
                }, {
                        "key": 2,
                        "value": "diamond"
                }, {
                        "key": 3,
                        "value": "u0000¨odÆ·u0005u0000"
                }]
        },
        ......
}

利用这些信息,可以进行 data file 级别的初步过滤,把不符合条件的 data file 过滤掉,进而减少一部分数据的读取。

实现索引的必要性

既然 Iceberg 已经提供 data file 级别的过滤。为什么我们还需要引入索引呢?以下面例子进行介绍,左边两个表格分别是 data file 文件里面的内容,右边表格是 data file 对应的 manifest file。

 

图片

 

针对SELECT * FROM table WHERE age > 50,利用 min-max 统计信息,很容易发现 data file 1 中没有满足条件的数据,因此 data file 1 就不会参与计算。

但是针对多维分析,如name = 'LiLy' AND age > 30,利用nameage的min-max的统计信息分别对条件name = 'LiLy'age > 30进行判断,得到 data file 1 和 data file 2 都满足条件。然而,仔细分析 data file 1 和 data file 2 的数据,并不存在符合条件的数据,因此 min-max 过滤效果不太理想。所以通过引入合适的索引功能,可以提高 data skipping 的概率,提高查询性能。

1.  首先探究索引类型

索引类型有多种,如 BloomFilter、Ribbon Filter、Dictionary Index、BitMap 等。为了满足多维分析场景,我们选择了[Range-Encoded BitMap]https://www.featurebase.com/blog/range-encoded-bitmaps ( Base-2, Bit-sliced Index),可适用于高基数场景,满足=、<、>、IN、BETWEEN 等操作的多维分析。

例如,对上面的 name 和 age 两列分别计算索引信息。由于 name 属于字符串类型,需要先进行字典编码再进行计算索引信息。采用 Range-Encoded 技术,根据数据的二进制相关信息以及对应的 pos 信息生成索引数据。利用索引数据分析得到,同时满足name = 'LiLy' 和age > 30的数据不在同一行,恰好可利用 Range-Encoded 的交并运算将数据进行过滤掉,因此 data file 1 不用参与计算。

也就是说,BitMap 的交并运算可以更好地在复杂过滤条件的情况下过滤掉更多的数据文件。

 

图片

 

2.  接下来探究索引的粒度。

Iceberg 提供的 min-max,也是一种文件级别的索引。文件级别的索引就是根据 filter 条件过滤掉不符合条件的 data file。文件级别的索引可适用于多种文件类型,但这种粒度比较粗,只要 data file 中有一条数据符合条件,该 data file 中的数据就会全部读取出来参与计算,从而影响 SQL 的查询性能。

对于 Parquet、ORC 的文件格式,提供有 file chunk 的概念(row group or stripe),我们完全可以按照 row group / stripe 粒度,对数据进行过滤。(为了方便描述,我们将 row group 和 stripe 统称 split。)

如:SQL语句:SELECT * FROM table WHERE col_1> v1 AND col_2 = v2,其中对 col_1 字段和 col_2 字段已构建 Index 信息。现在利用索引对 SQL 语句作用。

 

图片

 

SQL 语句解析后,将符合条件的 data file 列表进行切分后,得到很多 split 的列表。利用索引,分析 split 中数据是否满足条件,如果不满足则跳过。如上图 data file 列表切分后,得到数万级别数量的 split 列表。将索引数据作用在 split1,发现 split1 中没有同时col_1> v1 AND col_2 = v2满足条件的数据,该 split1 中的数据就不会参与计算。最后处理后,只得到了少量的 split 列表,数据过滤度达到 10% 以上,查询性能有明显提升。

因此,采用 row group / stripe 级别的细粒度索引,可以过滤大部分数据。

细粒度索引实现逻辑

Iceberg 元数据中 manifest file 中除了提供 min-max 等统计信息,还提供有 split 相关信息:"split_offsets":{"array":[4,...]},极大方便我们实现 row group / stripe 级别的细粒度索引。

  1. 提供索引的构建 API

Iceberg 中提供构建索引的 API,引擎端调用该 API 即可实现索引构建功能。对于 Spark 3.3 及以上版本,已经提供有索引的 SQL 语句,在 Iceberg 的 Spark 模块实现 Spark 提供的索引接口即可。

  1. 构建索引

我们采用异步构建索引,不影响主线任务。也提供了增量构建索引功能,只对 Append 数据进行构建索引。调用 TableScan 读取数据,按照 data file 的 split offset 切分数据,进行构建索引,并保存索引数据和对应的元数据信息。为了避免出现小文件存在,我们会进行索引数据合并。

  1. 索引文件存储

索引文件格式采用[puffin]https://iceberg.apache.org/puffin-spec/格式,这是一种二进制格式。Magic Blob₁ Blob₂ ... Blobₙ Footer

在 Footer 中保存每个 blob 的元数据信息。索引构建成功后,会生成类似于下面内容的文件。

 

图片

 

索引带来的收益

Range-Encoded BitMap 适用于多维分析场景,且 Ranger 范围较小时,效果非常明显。下面我们基于 Spark 引擎性能测试。

  1. 构造 1TB 的 SSB 测试数据,分别在构建 Index 前后,对以下用例进行测试。
Q1: SELECT count(*) FROM lineorder WHERE  lo_ordtotalprice = 19665277
Q2: SELECT count(*) FROM lineorder WHERE  lo_ordtotalprice = 19665277 AND lo_revenue  = 2141624
Q3: SELECT count(*) FROM lineorder WHERE  lo_ordtotalprice = 19665277 AND lo_revenue  >=10304000
Q4: SELECT count(*) FROM lineorder WHERE  lo_ordtotalprice = 21877827 AND lo_revenue  >= 83800  AND lo_revenue  <= 103800
Q5: SELECT count(*) FROM lineorder WHERE  lo_ordtotalprice > 21877827 AND lo_revenue  >= 83800  AND lo_revenue  <= 93800
Q6: SELECT count(*) FROM lineorder WHERE lo_ordtotalprice >= 93565 AND   lo_ordtotalprice < 93909
Q7: SELECT count(*) FROM lineorder WHERE   lo_ordtotalprice >= 93565 AND   lo_ordtotalprice < 91003562 AND lo_revenue    >=904300 AND lo_revenue    <= 9904300

 

图片

 

左图展示了 7 条 SQL 语句分别在没有 Index 和采用 Index 情况下的执行时间。右图展示采用 Index 后,7 条 SQL 语句读数据的 split 数量。很明显读数据的 split 数量越少,Index 效果越好。最糟糕的情况,所有的 split 都参数计算,这时和没有构建索引的效果类似。

  1. 采用 SSB 基准测试

由于 SSB 提供的测试场景,和 Range-Encoded 有利的场景,不太匹配,所以 Index 的效果并没有明显的效果。但也不会比不采用 Index 的效果差。如下面左图,分别是构建索引前后,SQL 语句的执行时间,构建索引的优势并没有体现出来。右图中,可以看到所有的 split 都参与了计算。

 

图片

 

总结

根据上面的介绍,这里总结下 Iceberg 中索引实现的一些特征:

  • 细粒度索引级别:提供 RowGroup/Stripe 级别的索引,可以更加精确的定位数据的查询范围,减少不必要数据输入,从而提高查询性能;
  • 索引作用于执行端:查询任务被分配多个执行端,每个执行端只判断该节点上的 RowGroup/Stripe 数据是否符合即可;
  • 适配多种引擎:索引构建后,可用于多种引擎;
  • 提供异步构建 Index,从而不影响主业务的进行;
  • 适用于高基数 & 低基数场景,且占有存储空间小。满足范围查询、等值查询等场景。且范围越小,收益效果越明显。


Tags:Apache   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
如何使用Python、Apache Kafka和云平台构建健壮的实时数据管道
译者 | 李睿审校 | 重楼在当今竞争激烈的市场环境中,为了生存和发展,企业必须能够实时收集、处理和响应数据。无论是检测欺诈、个性化用户体验还是监控系统,现在都需要接近即时...【详细内容】
2024-01-26  Search: Apache  点击:(47)  评论:(0)  加入收藏
Apache RocketMQ 5.0腾讯云落地实践
Apache RocketMQ 发展历程回顾RocketMQ 最早诞生于淘宝的在线电商交易场景,经过了历年双十一大促流量洪峰的打磨,2016年捐献给 Apache 社区,成为 Apache 社区的顶级项目,并在国...【详细内容】
2023-12-13  Search: Apache  点击:(132)  评论:(0)  加入收藏
利用Apache Kafka、Flink和Druid构建实时数据架构
译者 | 陈峻审校 | 重楼如今,对于使用批处理工作流程的数据团队而言,要满足业务的实时要求并非易事。从数据的交付、处理到分析,整个批处理工作流往往需要大量的等待,其中包括:等...【详细内容】
2023-12-11  Search: Apache  点击:(232)  评论:(0)  加入收藏
Contentsquare 使用微服务和 Apache Kafka 来发送通知
作者 | Rafal Gancarz译者 | 平川策划 | TinaContentsquare 平台的许多场景都需要通知功能。作为其微服务架构的一部分,该公司创建了一个跨多个服务的通用解决方案。在实现过...【详细内容】
2023-10-29  Search: Apache  点击:(331)  评论:(0)  加入收藏
如何确定Apache Kafka的大小和规模
作者丨Andrew Mills编译丨云昭调整或扩展Kafka以获得最佳成本和性能的第一步是了解数据流平台如何使用资源。这里给一些实用的建议。实现Apache Kafka的团队,或者扩展他们对...【详细内容】
2023-10-23  Search: Apache  点击:(329)  评论:(0)  加入收藏
什么让 Apache Kafka 如此快速?
Kafka 支持高吞吐量、高度分布式、容错性强的平台,能够以低延迟传递消息。有几种技术使 Apache Kafka 如此快速: 低延迟消息传递 批量数据和压缩 水平扩展低延迟消息传递大多...【详细内容】
2023-09-12  Search: Apache  点击:(350)  评论:(0)  加入收藏
Go语言开发者的Apache Arrow使用指南:内存管理
如果你看了上一篇《Go语言开发者的Apache Arrow使用指南:数据类型》[1]中的诸多Go操作arrow的代码示例,你很可能会被代码中大量使用的Retain和Release方法搞晕。不光大家有这...【详细内容】
2023-09-11  Search: Apache  点击:(266)  评论:(0)  加入收藏
Apache Iceberg 在严选批流一体的实践
Iceberg是数据湖解决方案中比较热门的方案之一,通常用于批流一体中数据存储的组织实现,希望通过本文让大家了解到严选是如何从老的Lambda架构升级到基于Iceberg的批流一体架构...【详细内容】
2023-09-04  Search: Apache  点击:(282)  评论:(0)  加入收藏
Set集合工具类Apache之SetUtils
本文主要讲述:集合工具类Apache之 org.apache.commons.collections4.SetUtils上文介绍了关于ListUtils的实例,本文我们对SetUtils的部分用法进行演示。一、判断两Set集合是否...【详细内容】
2023-08-14  Search: Apache  点击:(222)  评论:(0)  加入收藏
Apache Spark 的新编程语言
English SDK for Spark : 将英语作为一种新的编程语言,将生成式 AI 当做编译器, 将 Python 视作字节码!本文主要介绍了 Apache Spark 的英语软件开发套件(SDK)的重要性和目标,以及...【详细内容】
2023-07-07  Search: Apache  点击:(239)  评论:(0)  加入收藏
▌简易百科推荐
为什么Nginx被称为“反向”代理呢?
Nginx(发音为"engine-x")是一款高性能、轻量级的开源Web服务器软件,也可用作反向代理服务器、负载均衡器和HTTP缓存。Nginx之所以有被称为“反向”代理,是因为它充当客户端设备...【详细内容】
2024-02-01  coderidea  微信公众号  Tags:Nginx   点击:(60)  评论:(0)  加入收藏
哪种服务器操作系统更好呢?
在当今的IT世界中,服务器操作系统扮演着至关重要的角色。它们是确保服务器能够高效、安全地运行的关键因素。然而,对于许多人来说,服务器操作系统的种类和特点可能是一个复杂的...【详细内容】
2024-01-30    简易百科  Tags:操作系统   点击:(76)  评论:(0)  加入收藏
什么是VPS服务器
VPS服务器是一种虚拟化技术,它将一台物理服务器划分为多个虚拟的独立服务器,每个虚拟服务器都可以拥有自己的操作系统、运行环境、应用程序等。这种技术使得每个虚拟服务器可...【详细内容】
2024-01-30    简易百科  Tags:VPS服务器   点击:(70)  评论:(0)  加入收藏
VPS服务器下载速度慢?这五招帮你提速
VPS服务器下载速度慢可能会让用户感到沮丧,尤其是对于需要大量下载和上传数据的用户。幸运的是,有一些方法可以帮助您提高VPS服务器的下载速度,使您的在线体验更加顺畅。在本文...【详细内容】
2024-01-30  IDC行业观察者    Tags:VPS服务器   点击:(57)  评论:(0)  加入收藏
美国VPS和英国VPS:地理位置对服务器性能的影响
在今天的数字时代,VPS已成为在线业务和网站托管的关键组成部分。然而,选择合适的VPS主机服务时,地理位置通常被忽视,尽管它对服务器性能有着重要的影响。本文将探讨美国VPS和英...【详细内容】
2024-01-26  IDC行业观察者    Tags:服务器   点击:(55)  评论:(0)  加入收藏
如何判断服务器所需带宽:基于业务需求和流量模式的关键考量
在选择服务器时,带宽是一个重要的考虑因素。带宽的大小直接影响到网站的加载速度和用户的访问体验。那么,如何判断服务器需要多大的带宽呢?本文将为你揭示这一关键问题的答案...【详细内容】
2024-01-26  源库科技    Tags:服务器   点击:(74)  评论:(0)  加入收藏
服务器内存空间及IO操作原理解析
服务器的内存空间分为内核空间和用户空间,而我们编写的程序通常在用户空间中运行。在进行读写操作时,我们直接操作的是用户缓冲区,而用户缓冲区的内容来自于内核缓冲区。这种内...【详细内容】
2024-01-23  王建立    Tags:服务器   点击:(44)  评论:(0)  加入收藏
如何在Java环境中安装Nginx?
1. 下载Nginx:首先,前往Nginx官方网站(https://nginx.org/en/download.html)下载新版本的Nginx。选择适合您操作系统的版本,通常有Windows、Linux和Mac等不同操作系统的版本可供...【详细内容】
2024-01-22  敲代码的小动    Tags:Nginx   点击:(61)  评论:(0)  加入收藏
服务器证书和SSL证书有啥区别?
在互联网经济时代,随着越来越多的信息以及合作都是从企业官网开始的,因此绝大多数企业都会为自己的网站配置SSL证书,以提高安全性。在接触SSL证书时,也有很多人称之为服务器证书...【详细内容】
2024-01-10  安信SSL证书    Tags:服务器证书   点击:(65)  评论:(0)  加入收藏
宝塔面板怎样部署java项目?
宝塔面板怎样部署java项目?在使用宝塔面板部署Java项目之前,需要确保已经安装了Java Development Kit (JDK)。接下来,将介绍如何使用宝塔面板来部署Java项目的步骤。步骤一:安装...【详细内容】
2024-01-09  西部数码    Tags:宝塔面板   点击:(112)  评论:(0)  加入收藏
站内最新
站内热门
站内头条