前言

虽然之前也在Github上尝试提过一些PR,但都是一些doc、typo等类型的入门实践。真正算得上有一定实质性工作,要数最近在Apache IoTDB上提交的一个功能PR.如果大家对开源感兴趣的话,可以看我的一篇关于开源介绍的文章(开源介绍).如果大家对文中提到的比如Github、PR等词汇不熟悉建议可以先去学习一下Git,注册使用Github网站。

如何开始入手开源呢?

首先可以根据自身情况选择一个开源项目进行着手,熟悉项目,在社区学习,先做些简单issue,慢慢推进,默默发育,升级打怪,最后成为Committer甚至PMC,可以hold住功能模块开发,重要bug修复,架构设计等等~。由于本人对于Java语言相对熟悉,同时因为某些原因对于时序数据库有一定了解,经过一番搜索最终选择了Apache IoTDB.

好了~废话不多说,回归正传。

入门熟悉项目

一般来说,一个质量比较好的开源项目,其代码仓库的README文件或者官方文档会有比较详细的开发指南。Apache IoTDB也不例外,下面是我列的几个在这当中对我帮助比较大的几个文档。

用户指南: 用户指南

代码贡献指南:代码贡献指南、如何提交PR

设计实现文档:  设计实现文档

  • 用户指南:重点是学习该项目的一些功能、概念,这在后面阅读熟悉其代码是很有帮助的,比如在Apache IoTDB里的数据模型:存储组、路径等概念对于理解里面一些类的命名与作用会起到事半功倍的效果。
  • 代码贡献指南: 参与Apache IoTDB的一些流程,重点就是订阅官方邮件,在进行相关功能开发时可以先发一个邮件给社区的成员同步一下;在JIRA上领取issue;下载代码、格式化以及调试。特别是调试,在熟悉代码时如果实在不理解可以考虑进行调试。(正所谓一言不合就调试~)。最后就是感觉开发完成,如何提交PR的一个流程介绍。
  • 设计实现文档:是社区的一些开发人员编写的一些项目的设计实现流程,不过实话实说,IoTDB的这个文档写的对于小白不是特别友好,我一般更愿意去看代码,如果有困难再去找找相关部分的设计文档辅助代码阅读。

领取issue进行开发

我在Aapche IoTDB的JIRA上领取了issue,这个issue是关于一个语法功能上的扩展。

原先IoTDB在返回结果集上进行空值过滤仅支持比较粗粒度的without null all(即针对结果集中的如果所有列都为null则过滤该行)和without null any(即针对结果集中的如果所有列都为null则过滤该行)。

现在需要支持without null子句针对某几列生效,原先默认是对一行中所有列生效。

查询总体流程熟悉

由于该功能总体上可以归结为查询功能的一个小模块,所以我首先先要对IoTDB在执行一条查询语句的总体流程有一个大致的全局概念,后面再慢慢深挖without null子句在其中的一些处理逻辑。其总体的处理逻辑如下:

  • IoTDB在总体上是属于一种客户端-服务器架构,命令行客户端在与数据库服务器通信使用的是thrift RPC框架,一个查询SQL语句过来基本都是RPC调用的TSServiceImpl的executeStatement()方法;
  • 一条SQL字符串会先经过语法分析,在IoTDB里使用的Antlr进行SQL的语法解析,在使用Visitor模式遍历SQL的AST树时会将去转换成其内部的一个QueryOperator,在经过逻辑计划优化(目前好像优化没有像传统关系型数据库一样,不是很多),然后转化成一个物理执行计划。最后将其封装成一个QueryTask对象放进线程池去执行,执行完就返回RPC执行结果。

梳理without null处理逻辑的代码位置

本着以目标为导向,开始梳理原有代码中without null子句处理逻辑位置,从中获取需要改动的位置、边界以及如何改动的灵感。在原有代码中对without null语句的处理有四处,如下所示:

1. UDTFAlignByTimeDataSet类的fillBuffer()方法

public TSQueryDataSet fillBuffer(int fetchSize, WatermarkEncoder encoder) {
、、、  if (withoutAllNull || withoutAnyNull) {int nullFieldsCnt = 0;for (LayerPointReader reader : transformers) {if (!reader.next() || reader.currentTime() != minTime || reader.isCurrentNull()) {nullFieldsCnt++;}}
、、、
}

2. RawQueryDataSetWithoutValueFilter类的fillBuffer()方法

public TSQueryDataSet fillBuffer(int fetchSize, WatermarkEncoder encoder) {
、、、if (withoutAnyNull && filterRowRecord(seriesNum, minTime)) {continue;}
、、、
}

3. QueryDataSetUtils类的convertQueryDataSetByFetchSize()方法

public static TSQueryDataSet convertQueryDataSetByFetchSize() {
、、、
// filter rows whose columns are null according to the ruleif ((queryDataSet.isWithoutAllNull() && rowRecord.isAllNull())|| (queryDataSet.isWithoutAnyNull() && rowRecord.hasNullField())) {// if the current RowRecord doesn't satisfy, we should also decrease AlreadyReturnedRowNumqueryDataSet.decreaseAlreadyReturnedRowNum();i--;continue;}
、、、
}

4. QueryDataSet类的hasNext()方法

public boolean hasNext() throws IOException {// proceed to the OFFSET row by skipping rowswhile (rowOffset > 0) {if (hasNextWithoutConstraint()) {RowRecord rowRecord = nextWithoutConstraint(); // DO NOT use next()// filter rows whose columns are null according to the ruleif ((withoutAllNull && rowRecord.isAllNull())|| (withoutAnyNull && rowRecord.hasNullField())) {continue;}rowOffset--;} else {return false;}}// make sure within the LIMIT constraint if existsif (rowLimit > 0 && alreadyReturnedRowNum >= rowLimit) {return false;}return hasNextWithoutConstraint();
}

解决方案初步形成

通过前面对于without null处理逻辑的梳理,不难发现都是在对结果集的每一行进行判断是不是所有列都为null或者存在null.

所以其实只要我们在这些位置如果将判断null的范围限定到without null指定的那些列,至于其他列直接忽略就行。于是一个很朴素的想法就出现了,由于它每一行是按数组索引的形式遍历每一列的值,有的不包括列名信息,如果我能找到without null指定的列名在遍历的结果集的每一行的与其相应的索引的映射关系就可以了。

所以在到达上述的四个位置时,我要维护得到一个WithoutNullColumnIndexSet集合,在遍历每一个RowRecord时去判断其为null列的索引是否在WithoutNullColumnIndexSet中即可。

遇到的一些困难

1. select语句后面跟的列名与without null指定的列名并不是那么简单的字符串相等关系,而且还有可能有别名信息,以及一些整合名(与from后的路径拼接、group by level等);一个比较典型的例子就是select * from xxx without null (s1);

解决:从Antlr语法层面,select 后面跟的column是一个expression,而刚好without null后面跟的column也是一个expression。在原有逻辑中已经包含了对解析到的select的column的表达式的一些transform(比如去*、拼接路径等等),我再处理without null可以复用这段逻辑跟着进行变换。这样在其内部处理表示中就会是一个equals的关系,这样就可以很方便地进行元数据校验(without null里指定的列是否与select的column名相一致),以及填充WithoutNullColumnIndexSet,当然这里要注意别名的考虑。

2. 原有IoTDB的Query类型众多,而且处理逻辑并不是完全统一,要考虑一些特殊类型的查询,比如AlignByDevice、对齐时间序列等

在原有的正常的AlignByTime查询中,存在一个pathToIndex变量可以帮助我更快形成WithoutNullColumnIndexSet,但在AlignByDevice中这个pathToIndex是空的,它有另一套逻辑去维护结果集列名与设备名之间的关系。

而对齐时间序列的数据类型,并不想原始数据类型,它是一个类似数组的结构,在原有RowRecord中它只占一列但其实其内部会展开成多列,原来逻辑只会告诉你它内部包含的列是否全为null或者部分为null。如果without null指定其中的某几列就会出现不正确的问题。针对这种情况在维护index信息时就不能使用外部的那个只占一列信息,而应该去遍历其内部包含的列名,从而得到真正的正确的WithoutNullColumnIndexSet。

3. 原有代码中,without null存在一个bug

提bug issue,先把这个bug解决再继续接下来的开发。

提交PR

在开发完成,编写自测通过、编写相应的用户使用文档后,根据上面的提交PR指南,提了PR,功能PR是有两位社区人员进行Review,根据他们提出的一些建议与问题,前前后后又改了几天,最后终于Merge了~

我的第一次实质性开源贡献——Apache IoTDB相关推荐

  1. 【fly-iot飞凡物联】(5):开源项目Apache IoTDB,开源项目学习,原来还有这样的项目,关于IOT的几个开源项目汇总下

    目录 前言 1,关于:开源项目Apache IoTDB 2,还有个admin后台 3,thinglinks项目 4,thingsboard-ui-vue项目 5,apache pulsar项目 6,A ...

  2. 腾讯技术直播间 | Apache IoTDB x Apache Pulsar Meetup

    点击下方图片 收看Apache软件基金会两大孵化器项目 Pulsar x IoTDB 分享会全程直播 ???? >>> 活动介绍 <<< Apache Pulsar ...

  3. 清华自研时间序列数据库Apache IoTDB原理解析

    云智慧 AIOps 社区是由云智慧发起,针对运维业务场景,提供算法.算力.数据集整体的服务体系及智能运维业务场景的解决方案交流社区.该社区致力于传播 AIOps 技术,旨在与各行业客户.用户.研究者和 ...

  4. Apache IoTDB PMC 乔嘉林荣获 2022 杰出开源贡献者|开源技术强大,开源文化活跃...

    2022 年 12 月 29 日至 30 日,2022 木兰峰会正式召开,会上发布了中国开源云联盟 2022 年度评选名单.本次评审专家包括数十位开源领域专家.社区领袖.科研院所专家,共评选出杰出开源 ...

  5. 如何成为一名合格的Apache项目Committer,参与Apache开源贡献的正确姿势

    近日,孙金城老师在 "Open Source Promotion Plan - Summer 2020" 开源软件供应链点亮计划做了<如何成为一名合格的Apache项目Com ...

  6. 墨天轮沙龙 | 清华乔嘉林:Apache IoTDB,源于清华,建设开源生态之路

    在6月8日举办的[墨天轮数据库沙龙第七期-开源生态专场]中,清华大学博士,助理研究员,Apache IoTDB PMC 乔嘉林老师分享了<Apache IoTDB,源于清华,建设开源生态之路&g ...

  7. 迎新:Apache IoTDB 喜迎 2 位新 Committer

    正文 1222 字,预计阅读时间 4 分钟. Apache IoTDB 是一个开源物联网时序数据库,旨在满足大规模物联网和工业物联网(IoT 和 IIoT)应用对数据.存储和分析的严苛要求. 不完全统 ...

  8. 2022 Apache IoTDB 物联网生态大会成功举办,见证工业数据已然创造的未来

    大会圆满落幕 干货内容公布 2022年12月3日.4日,由中国通信学会作为指导单位,Apache IoTDB Community.清华大学软件学院.中国通信学会开源技术委员会联合主办,"科创 ...

  9. 2022 Apache IoTDB 物联网生态大会 | 议题嘉宾公布,大会亮点抢先看!

    议题&嘉宾公布 大会亮点抢先看! 2022ApacheIoTDB物联网生态大会将于12月3日.4日的9:30-16:30进行线上直播.本次大会由中国通信学会作为指导单位,Apache IoTD ...

最新文章

  1. LVM创建,缩减及快照备份
  2. node封装mysql模块
  3. springboot 第四讲
  4. sql优化的方法及思路_合理的sql优化思路--如何缩短SQL调优时间?
  5. python汽车行驶工况_什么叫车辆行驶工况
  6. 第一张信用卡,该选哪家的?
  7. 在linux实现公平队列,多级反馈队列调度策略在Linux中的应用和实现.pdf
  8. android 双卡流量统计,android流量统计
  9. Atitit USRqc62204 证书管理器标准化规范
  10. git学习笔记-(3-linux基本命令)
  11. NR 5G 网络功能之UPF
  12. html页面pc端显示正常,手机端页面整体偏左(兼容性处理)
  13. tomcat下载指定版本
  14. 7-5 体脂率换算(男女皆可计算)
  15. Fibonacci数列练习题
  16. Ansible系列-基础篇-Ansible Inventory的合理化配置
  17. 最简单的方式实现竖排文字显示
  18. AngularJS中的$resource使用与Restful资源交互
  19. PL/SQL用户指南与参考(第一章)
  20. 知乎上48个神回复,真心值得一看!

热门文章

  1. 第二届天府大地艺术季(春)分会场暨晨光社区系列主题活动开启
  2. Powershell批量禁用指定用户及将禁用用户移动到指定OU
  3. ZJOI2006书架Treap做法
  4. 毕业设计 - 题目:基于python的验证码识别 - 机器视觉 验证码识别
  5. 反弹shell 之最终篇 实战远操
  6. Ubuntu20.04 桌面配置
  7. OSD(On Screen Display )技术(转)
  8. 2020.10.5-10.12 人工智能行业每周技术精华文章汇总
  9. 水星(MERCURY)MW150RM迷你无线路由器Client模式设置
  10. 暴力突破 Java 并发 - synchronize 解析