Google Dremel和parquet的复杂嵌套数据结构表征方法解析

转载请注明出处。作者:archimekai
核心参考文献: Dremel: Interactive Analysis of Web-Scale Datasets

文章目录

  • 引言
  • 复杂嵌套数据结构的无损表征问题
  • Dremel论文中提出的表征方法
  • parquet
  • 备注

引言

Dremel是Google的交互式分析系统。Google大量采用protobuf格式,因此Dremel必须支持protobuf这种复杂嵌套格式的分析。众多工作已经论证了列式存储格式对分析系统(AP, analytical processing)的重要性,因此Dremel需要把复杂嵌套格式存储为列存。本文接下来重点分析Dremel是如何把复杂嵌套格式转换为每一列单独存储的。

我们的目标是:没有蛀牙(划掉)把相同字段的所有值连续存储。因此需要设计一种能够适用于任意protobuf/json格式的,无损的数据表征方式。

复杂嵌套数据结构的无损表征问题

不同的数据,其表征难度是不同的。最简单的是完全没有嵌套,平铺直叙的数据。这种数据只要将每一个字段的名称取出,放在数据库中作为一列即可。
数据样例如下:

{"Code": "en-us", "Country": "us"}

一种表征方式如下:

CodeCountry
en-usus

如果数据中有嵌套,但是没有列表,也比较简单。只需要用某个分隔符(例如 . )把嵌套的字段名称连接起来即可。以下面的数据为例:

{"DocId": 10, "Links": {"Forward": 20}}

其一种表征方式如下:

DocIdLinks.Forward
1020

如果数据中存在列表,就比较复杂了。这里的难点在于,列表的长度无法提前预知,所以一般不能把列表中的每一个元素都作为一列存储。例如

{"Links": {"Backward": [10,30], "Forward": [80]}}

不能表征为

Links.Backward[0]Links.Backward[1]Links.Forward[0]
103080

如果将来Backward中有10000个元素就很难处理。

这个问题其实有一个简单场景,即列表中的元素都是相同的基本数据类型。这里的基本数据类型可以简单理解为数据库有原生数组类型支持的数据类型,例如 int ( int[] ),float ( float[] )等,因此,上述数据可以表征为下表。Hologres就是采用了这样的方案。

Links.BackwardLinks.Forward
[10.30][80]

通过上面的方案,笔者认为已经可以搞定80%以上的场景了。但是如果列表中的元素不是基本数据类型,上面的的方案就又搞不定了。考虑下面的数据:

{"Name": [{"url": "http://C", "long_data": "data"}]}

在这个例子中,数组里面的元素是{"url": "http://C"},并不是一种基本数据类型,如何存储才能支撑对Name.url的高效查询呢?。除了上面的例子,还有更为复杂的数组套数组的例子:

{"Name": [{"Language":[{"Code": "en-us", "Country": "us"}, {"Code": "en"}]}]}

那么,有没有一种方法可以一劳永逸地搞定所有protobuf/强类型json(强类型json指每个字段的类型是确定的)能够表达的所有数据呢?还真有,这就是Google的天才工程师们在Dremel论文中提出的方案。下面笔者重点介绍这个方案。

Dremel论文中提出的表征方法

还是看上面数组套数组的例子,主要的困难点是,读取数据时如何确定内层元素(例如{"Code": "en"})的位置?这需要准确表达内层元素在当前数组(也即Language)和父数组(也即Name)中的位置,才能在读取时把数据结构还原回来。这提示我们,至少需要增加两个位置信息才行。
Google的工程师们也是这么想的,他们定义了两个变量来表示上述信息,这两个变量也是理解Dremel数据表征算法的关键:

  • 第一个变量是repetition level,简称r,其表示对于给定的字段,其当前在哪一个级别重复。这个概念比较抽象,请结合下面的例子仔细阅读备注进行理解。
  • 第二个变量是definition level,简称d,其表示对于给定的字段,其前面有多少个字段是存在的。例如,r3中的DocId,d=0,也即DocId更上层没有字段了,r3中的Links.Forward字段,d=1,也即Links这个字段是存在的。

可以看到,r和d并非直接表示当前数组和父数组的位置,而是以一种类似增量(在当前级别重复还是在哪个级别重复)的方式进行编码。

一个加料版的例子(r3,基于论文中的r1修改而来)。数据schema如下

message Document { 
required int64 DocId; optional group Links { 
repeated int64 Backward; 
repeated int64 Forward; } 
repeated group Name { repeated group Language { 
required string Code; 
optional string Country; } 
optional string Url; }} 

数据如下(简称r3)

{"DocId": 10, "Links": {"Forward": [20,40,60]}, "Name": [{"Language": [{"Code": "en-us", "Country": "us"},{"Code": "en"},{"Code": "zh-cn", "Country": "cn"}]"Url": "http://A"},{"Url": "http://B"},{"Language": [{"Code": "en-us", "Country": "gb"}]}]
}

数据r3中的Name.Language.Country字段编码后如下。

valuerd备注
us02r=0表示r3这篇文档的第一个Country字段,d=2表示Name, Language两个字段都是存在的
null22r=2表示Language字段在第二级,也即Language数组这一级重复,null表示Country字段实际上未在Language这个数组的第二个元素{"Code": "en"}中出现。注意null在dremel的编码方式中是必须的
cn22r=2表示Language字段在第二级,也即Language数组这一级重复,出现在Language这个数组的第三个元素
null11r=1表示Language字段在第一级,也即Name数组这一级重复,null表示Country字段实际上为在Name这个数组的第二个元素{"Url": "http://B"}中出现。结合d=1可知,Name.Language.Country中只有头一个字段,也即Name存在,Language字段不存在。
gb12r=1表示Language字段在第一级,也即Name数组这一级重复,出现在Name数组的第三个元素

到了这里,相信读者已基本理解了r和d的含义。笔者将Dremel论文中的原图贴在这里,大家应该可以看懂了。
Dremel论文原文中的例子

parquet

parquet中对于嵌套数据的数据和Google Dremel基本一致。本篇文章不详细展开

备注

  • 为了方便理解,上述描述中省略了一些不重要的细节,感兴趣的读者可自行阅读论文原文。
  • 本篇文章只介绍了最核心的数据结构表征方式,Dremel论文中还有关于如何将各个字段拆分为列,如何使用有限状态自动机真正生成r和d值的描述,以后有机会再介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建服务器及跨域处理

使用内置的模块搭建服务器 自己电脑: 域名:localhost ip:127.0.0.1 http模块搭建服务器 const http = require(http)// 创建一个http对应的服务器,每次改完服务器的代码后都需要重新启动下服务器 /*方式一: const server = http.createServer((request,response)=>{…

铁路关基保护新规发布!铁路软件供应链安全洞察与治理思路

近日,国家铁路局发布《铁路关键信息基础设施安全保护管理办法》,《办法》第十四条提到:“运营者应当加强铁路关键信息基础设施供应链安全保护,优先采购安全可信的网络产品和服务。运营者采购网络产品和服务,应当预判该…

Intel FPGA IP之LVDS SerDes IP学习

FPGA 视频数据输入输出直通工程: 屏:13.2吋8bit色深,屏幕分辨率为1440*192060,具有两个Port,每个Port有4个差分数据对与1个差分时钟对,差分对均支持LVDS协议芯片:Cyclone V系列FPGA目的&#x…

Noise Conditional Score Networks(NCSN)学习

参考: [1] https://zhuanlan.zhihu.com/p/597490389 [2] https://www.zhangzhenhu.com/aigc/Score-Based_Generative_Models.html TOC 1 基于分数的生成模型1.1 简介和动机1.2 Score Matching及其改进1.2.1 Score Matching1.2.2 Sliced score matching(不…

XSS_lab(level1-level5)

level1 直接输入页面没有发现输入框&#xff0c;观察url发现有传参 尝试修改传参为&#xff1a;<script>alert(1)</script> 过啦&#xff01; level2 页面中有输入框&#xff0c;尝试构建语句&#xff1a;<script>alert(1)</script>,传输后查看源代…

国际心理学导师-叶子文JeffreyYip的《意识地图》

“物质就是能量。” ---爱因斯坦 “時常保持觉知&#xff0c;有意识地发现情绪起伏 你随时都能翻转人生 做自己人生的导演 当你频率高时&#xff0c;万事万物为你而来” ---大卫霍金斯 叶子文-《意识地图》&#xff1a;高阶心理学课程 宇宙间万物的本质是能量。一切都靠能量…

Java基础---lambda表达式

一、为什么要引入lambda表达式 lambda 表达式是一个可传递的代码块 &#xff0c; 可以在以后执行一次或多次 。 在介绍lambda表达式之前&#xff0c;我们看一下&#xff0c;以前&#xff0c;我们对于一个问题的通常写法。 假设你已经了解了如何按指定时间间隔完成工作&#xf…

js字符串转json的3种方法

1.eval方式解析 function strToJson(str){var json eval("(" str ")");return json;}console.log(strToJson("{int:1, string:demo}")); 运行截图&#xff1a; 注&#xff1a; 记得别忘了str两旁的小括号。 永远不要使用 eval !!! eval() 是一…

611. 有效三角形的个数 - 力扣

1. 题目 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 2. 示例 3. 分析 利用已升序了的数组通过 a b > c 这条公式找出符合要求的三元组&#xff0c;利用这个公式的前提是三条边为从小到大&#xff0c;再利用单调性快速统计…

STM32 (1)

1.基本信息 stm32是由ST公司生产的一种32位微控制器&#xff08;单片机&#xff09;。 1.1 各种型号 stm32是32位单片机的总称&#xff0c;有多种不同的系列。 32即用32个比特位表示一个地址&#xff0c;寻址范围&#xff1a;0x00000000 --0xffffffff (4GB) 1.2 存储密度 …

UE5中实现后处理深度描边

后处理深度描边可以通过取得边缘深度变化大的区域进行描边&#xff0c;一方面可以用来做角色的等距内描边&#xff0c;避免了菲尼尔边缘光不整齐的问题&#xff0c;另一方面可以结合场景扫描等特效使用&#xff0c;达到更丰富的效果&#xff1a; 后来解决了开启TAA十字线和锯齿…

XXL-Job的基本使用

一、市面上常见的任务调度产品 针对分布式任务调度的需求&#xff0c;市场上出现了很多的产品: 其中XXL-job 是我们经常使用的任务调度平台,XXL这三个英文字母.是以作者名许雪里命名的。 可以前往 Gitee 地址进行下载使用 https://gitee.com/xuxueli0323/xxl-job.git二、XXL-J…

第二十一周周报

文献阅读&#xff1a;Recent Advances of Monocular 2D and 3D Human Pose Estimation: A Deep Learning Perspective 摘要&#xff1a;在本文中&#xff0c;作者提供了一个全面的 2d到3d视角来解决单目人体姿态估计的问题。首先&#xff0c;全面总结了人体的二维和三维表征。…

Windows的Linux化持续推进中

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Java基础 - 6 - 面向对象(二)

Java基础 - 6 - 面向对象&#xff08;一&#xff09;-CSDN博客 二. 面向对象高级 2.1 static static叫做静态&#xff0c;可以修饰成员变量、成员方法 2.1.1 static修饰成员变量 成员变量按照有无static修饰&#xff0c;分为两种&#xff1a;类变量、实例变量&#xff08;对象…

故障诊断 | 一文解决,XGBoost极限梯度提升树的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,XGBoost极限梯度提升树的故障诊断(Matlab) 模型描述 XGBoost通过集成多个决策树来建立一个强大的预测模型。它采用了一种特殊的梯度提升技术,称为极限梯度提升(Extreme Gradient Boosting),以提高模型的性能和鲁棒性。 极限梯度…

【大数据Hive】hive 多字段分隔符使用详解

目录 一、前言 二、hive默认分隔符规则以及限制 2.1 正常示例&#xff1a;单字节分隔符数据加载示例 2.2 特殊格式的文本数据&#xff0c;分隔符为特殊字符 2.2.1 文本数据的字段中包含了分隔符 三、突破默认限制规则约束 3.1 数据加载不匹配情况 1 3.2 数据加载不匹配…

Java项目推荐|几个B站上的从零搭建项目

分享几个B站上搜集到的技术比较全&#xff0c;讲解也详细的Java后端开发项目 目录 谷粒商城 2020-03-31 iHRM 人力资源管理系统 2021-04-16 瑞吉外卖 2022-04-12 学成在线 2023-01-13 尚上优选 2023-06-06 黑马头条 2023-06-13 苍穹外卖 2023-07-05 谷粒商城 2020-03-3…

STM32FreeRTOS任务通知(STM32cube高效开发)

文章目录 一、任务通知(一&#xff09;任务通知概述1、任务通知可模拟队列和信号量2、任务通知优势和局限性 (二) 任务通知函数1、xTaskNotify&#xff08;&#xff09;发送通知值不返回先前通知值的函数2、xTaskNotifyFromISR&#xff08;&#xff09;发送通知函数ISR版本3、x…

Java面试题总结200道(二)

26、简述Spring中Bean的生命周期&#xff1f; 在原生的java环境中&#xff0c;一个新的对象的产生是我们用new()的方式产生出来的。在Spring的IOC容器中&#xff0c;将这一部分的工作帮我们完成了(Bean对象的管理)。既然是对象&#xff0c;就存在生命周期&#xff0c;也就是作用…