执行

上一篇讲述了如何通过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也进入了大众视野。

用scala实现一个sql执行引擎-(下)的更多相关文章

  1. 用scala实现一个sql执行引擎-(上)

    前言 在实时计算中,通常是从队列中收集原始数据,这种原始数据在内存中通常是一个java bean,把数据收集过来以后,通常会把数据落地到数据库,供后面的ETL使用.举个一个简单的例子,对一个游戏来说, ...

  2. 自己实现一个SQL解析引擎

    自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可运行的操作序列,并返回查询的结果集. SQL的解析引擎包含查询编译与查询优化和查询的执行,主要包含3个步骤: 查询分析: 制定逻 ...

  3. 自己动手写SQL执行引擎

    自己动手写SQL执行引擎 前言 在阅读了大量关于数据库的资料后,笔者情不自禁产生了一个造数据库轮子的想法.来验证一下自己对于数据库底层原理的掌握是否牢靠.在笔者的github中给这个database起 ...

  4. 给隔壁的妹子讲『一个SQL语句是如何执行的?』

    前言 SQL作为Web开发是永远离开不的一个话题,天天写SQL,可是你知道一个SQL是如何执行的吗? select name from user where id = 1; 上面是一个简单的查询语句, ...

  5. Oracle数据库该如何着手优化一个SQL

    这是个终极问题,因为优化本身的复杂性实在是难以总结的,很多时候优化的方法并不是用到了什么高深莫测的技术,而只是一个思想意识层面的差异,而这些都很可能连带导致性能表现上的巨大差异. 所以有时候我们应该先 ...

  6. SQL执行过程中的性能负载点

    一.SQL执行过程 1.用户连接数据库,执行SQL语句: 2.先在内存进行内存读,找到了所需数据就直接交给用户工作空间: 3.内存读失败,也就说在内存中没找到支持SQL所需数据,就进行物理读,也就是到 ...

  7. spark sql 执行计划生成案例

    前言 一个SQL从词法解析.语法解析.逻辑执行计划.物理执行计划最终转换为可以执行的RDD,中间经历了很多的步骤和流程.其中词法分析和语法分析均有ANTLR4完成,可以进一步学习ANTLR4的相关知识 ...

  8. hint不当索引,影响多表连接方式,最终导致SQL执行缓慢

    需求:一个SQL执行特别慢,无法返回结果,需要进行优化,最终返回结果即可. 一.SQL分析 二.尝试执行,观测执行计划 三.修改SQL 四.问题总结 一.SQL分析 )SQL文本,执行时间,执行用户 ...

  9. spring 默认情况下事务是惟一的 同一个方法里面第一个sql开启后 在执行完 将事务传递给下一个sql

    spring 默认情况下事务是惟一的 同一个方法里面第一个sql开启后 在执行完 将事务传递给下一个sql

随机推荐

  1. JAVA设计模式之合成模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述合成(Composite)模式的: 合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述 ...

  2. Create User - mysql

    Create User MariaDB [(none)]> CREATE USER 'DBAdmin'@'%' IDENTIFIED BY 'mypasswd';Query OK, 0 rows ...

  3. java基础回顾(八)——Queue

    今天回顾了下关于Queue的一些相关知识 我们可以看到,Deque也是一个接口,它继承了Queue的接口规范.其中LinkedList和ArrayDeque都是实现Deque接口,所以,可以说他们俩都 ...

  4. ios异常(crash)输出

    最近突然想起友盟的sdk附带的一个功能:将闪退异常情况上报服务器,(stackflow,github)找了一些资料,自己写了一个demo,想起来好久没有写过blog了,顺便分享. 其实不止是ios,a ...

  5. MSSQLSERVER之发布-分发-订阅

    一.环境 发布服务器 O S: Windows servier 2003 64位 Soft: Microsoft SqlServer 2008 R2 I P: 192.168.3.70 HOST-NA ...

  6. Hadoop HDFS编程 API入门系列之从本地上传文件到HDFS(一)

    不多说,直接上代码. 代码 package zhouls.bigdata.myWholeHadoop.HDFS.hdfs5; import java.io.IOException; import ja ...

  7. js生成二维码实例(真实有效)

    js文件  qrcode.js   代码 /*from tccdn minify at 2014-6-4 14:59:43,file:/cn/c/c/qrcode.js*/ /** * @fileov ...

  8. Bootstrap导航点击菜单跳转与点击缩放菜单折叠按钮缓冲效果插件jquery.singlePageNav.min.js

    引入步骤: <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></scrip ...

  9. Linux_09------Linux上系统扫描和安全策略

    先谢慕课网/** * linux系统扫描技术 * * 主机扫描.路由扫描.批量服务扫描.系统安全策略(防SYN和ddos攻击) */ /** * 主机扫描 * ping fping hping * * ...

  10. 重新认识Android

    首先我们来看下源码中源于Activity的定义: public class Activity extends ContextThemeWrapper implements LayoutInflater ...