用scala实现一个sql执行引擎-(下)

执行

上一篇讲述了如何通过scala提供的内置DSL支持,实现一个可以解析sql的解析器,这篇讲如何拿到了解析结果-AST以后,如何在数据上进行操作,得到我们想要的结果。之前说到,为什么选择scala作为这个引擎的实现,之一是scala提供了方便的DSL实现支持,其二是因为作为一门函数式编程语言,scala提供了丰富对于集合操作的函数。此外,函数在scala中是一个独立的类型,所以能够把现有的函数进行组合,得到更为强大的函数(和上一篇提到的用解析组合子组合已有的解析器得到更强大的解析器一样)。

首先,我们需要弄清楚普通sql语句的执行顺序一般来说,sql的书写顺序为

  • SELECT[DISTINCT]
  • FROM
  • WHERE
  • GROUP BY
  • HAVING
  • UNION
  • ORDER BY

但是,执行顺序为

  • FROM
  • WHERE
  • GROUP BY
  • HAVING
  • SELECT
  • DISTINCT
  • UNION
  • ORDER BY

本次实现的sql执行不支持join,所以省去了union部分,但是大致顺序差不多,如果把一个List<Map>想象成一个数据库的表,那么执行顺序可以用下图所示,图中标绿色的箭头表示可以并发执行,聚合函数的执行是不能并发的,但是因为已经把数据给分组了,故可以在更高的一个层次并发。

了解了大致的执行流程,下面说一下各个流程执行所用到的函数。

 

  • where子句
    where子句的执行,利用了 filter函数,将不符合条件的数据给过滤掉。举个例子,下面这个段代码,将列表中的奇数给过滤掉。
    scala> val L = List(1,2,3,4,5,6)
    L: List[Int] = List(1, 2, 3, 4, 5, 6)
    scala> L filter(_%2==0)
    res2: List[Int] = List(2, 4, 6)

    对每个元素进行判断这个步骤其实是可以并发执行的,你只需要这样写,就能进行安全的并发操作。

    scala> L.par.filter(_%2==0).toList
    res4: List[Int] = List(2, 4, 6)

    在scala_sql引擎中,实现where的函数为

    def where(where: Option[SqlExpr]): Table = {
          where match {
            case None => table
            case Some(x: SqlExpr) => table filter (evalWhereEachRow(_, x))
          }
        }

    其中evalWhereEachRow(_,x)是另外一个函数,第一个参数是table中的一列,即一个Map对象,第二个参数是由sql解析得到的AST中,对应where子句的部分。

  • groupBy子句
    scala中也提供了对于集合的groupBy操作,接着上个例子
    scala> L groupBy(_%2)
    res6: scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(1, 3, 5), 0 -> List(2, 4, 6))

    上面这个函数,把L这个list根据奇偶分组。
    在scala _sql引擎中,实现groupBy的函数为

     def evalGroupBy(table: Table, groupby: SqlGroupBy): Seq[Table] = {
        val keys: Seq[String] = groupby.keys map {
          case x: FieldIdent => x.name
        }
        table.groupBy(row => keys.map(row(_))).map(_._2).toSeq
      }

结论

DSL主要有两种,内部DSL和外部DSL,对于外部DSL,需要一个解析器来解析DSL的脚本,得到能够让程序处理的数据结构,这种数据结构通常是一种AST。实现需要的解析器,大体有两种方式:

  • 手工写一个,例如druid中的sql解析模块。
  • 利用ANTRL等解析生成器,通过编写语法规则,生成一个解析器。

近年来随着函数式编程慢慢得到工业界的关注,利用parser combinator(解析组合子)的方式来编写解析器实现DSL也进入了大众视野。

转载于:https://www.cnblogs.com/javanerd/p/4384070.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: flink-1.14.3-bin-scala_2.12 是Apache Flink的一个版本,它是一个基于分布式数据流处理的开源平台。Flink提供了高效的流处理和批处理能力,支持各种数据源和格式,具有高可用性、可伸缩性、易于使用和开发的特点。 其中,1.14.3代表这个版本是Apache Flink的第1.14.3个稳定版本,其中包含了性能优化、改进和新功能。Scala_2.12表示在这个版本中使用了Scala编程语言的2.12版本,这意味着这个版本支持Scala编程。 在flink-1.14.3-bin-scala_2.12中,最重要的新功能之一是针对Apache Kafka的完整支持。此外,还支持更优秀的可伸缩性,提供了更多的API变更和改进等。它还提供了一些改进,例如在任务重启时恢复状态,提高了批处理的性能和吞吐量。 总之,flink-1.14.3-bin-scala_2.12是一个高效、可伸缩、易于使用和开发的分布式数据流处理平台,支持流处理和批处理,被广泛用于企业级数据处理和实时数据分析。 ### 回答2: Flink-1.14.3-bin-scala_2.12是一个 Apache Flink 的软件发行版,主要针对 Scala 2.12 版本进行构建。Apache Flink是一个分布式流处理引擎,支持批量和流式数据处理和分析,并提供高可用性、可扩展性和容错性等特性。Flink-1.14.3-bin-scala_2.12是Apache Flink最新的稳定版本,其中包含了许多新的特性、改进和修复了一些前版本中存在的问题。在Flink-1.14.3-bin-scala_2.12中,采用了新的caching机制来提高性能,支持Kinesis Video Streams、Kudu、Flink SQL等新的特性,同时也优化了Flink Web Dashboard和Flink SQL Client的用户体验。Flink-1.14.3-bin-scala_2.12的使用需要一定的编程经验,可以使用Java、Scala或Python进行开发。此版本对于需要处理大规模数据的企业或个人提供了有力的支持,可以提高数据处理效率和准确性,同时也降低了使用成本和复杂度。 ### 回答3: Flink是一个大数据处理框架,其最新版本是flink-1.14.3。该版本支持Scala 2.12编程语言,并附带可执行二进制文件,文件名为“flink-1.14.3-bin-scala_2.12”。 该文件中包含了Flink的代码和相关依赖库,用户可以直接下载该文件并解压缩后即可开始使用Flink框架进行大数据处理。用户只需要将自己的程序代码打包成JAR文件,并提交给Flink集群运行,Flink就会自动管理和调度任务,实现高效的分布式计算。 该版本中包含了许多新的功能和改进,例如增强的流式数据处理能力、更简洁的API、更快的数据处理速度等。此外,该版本还修复了许多已知的问题和Bug,提高了Flink的稳定性和性能表现。 总之,flink-1.14.3-bin-scala_2.12是Flink框架的最新版本,其包含了许多有用的功能和改进,用户可以下载并使用该版本来进行高效的大数据处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值