美文网首页
查询编译与代码生成

查询编译与代码生成

作者: 玲珑塔上玲珑人 | 来源:发表于2020-07-01 17:04 被阅读0次

在内存数据库中提高吞吐量的唯一方式就是减少执行指令数目。
大多代码都是为了人能理解而不是单为了性能。
接下来从逻辑查询方面进行分析。

看下面的例子


查询解释1.png

根据这个例子可以得到一个查询树和查询计划。


查询解释2.png
这里的查询语句被优化器进行重写,重写成Join。查询树和查询计划很好理解,但是对于CPU而言很不友好,过多的结构和分支,无论for还是if都会产生大量的分支,导致CPU要不断刷新管道和缓存;大量的函数调用导致CPU在内存总不断跳跃。
谓词解释.png

在执行B.val = ? +1时,有参数输出,执行这一条语句需要传入参数、当前元组、当前元组所在表的格式,需要大量的函数调用,代价很大。

Code Specialization

一个 解决方式就是code specialization,产生专门针对DBMS task的代码来较少指令数量。
对于上面的操作而言,都是一些通用的查询编译过程,支持大多数查询。但是如果是不同的输入具有相似的执行模式,可以在本地编译任何数据库的CPU密集型实体,即对一些特殊的查询进行特定的编译设计。
访问方法
存储过程
操作员执行
谓词评估
记录操作

这样做的好处是

  1. 属性类型是先验已知的。
    数据访问函数调用可以转换为内联指针转换。
    即,可以直接通过offset访问元组中的某个属性。
  2. 谓词是先验已知的。
    可以使用原始数据直接比较来评估它们。
  3. 循环中没有函数调用
    允许编译器高效地将数据分发到寄存器并增加缓存重用。
    因为没有函数调用,所以只需要直接比较内存块的几个offset的某个size的数据的关系即可。

Code Generation 代码生成

两种方法

  1. 移植
    把关系查询计划转化为命令语言源码(C/C++),然后再用传统编译器来产生本地码

  2. JIT编译(LLVM)
    生成可快速编译为本地码的查询的中间表示(IR)

HIQUE - Code Generation
对于一个给定的查询计划,产生一个C/C++程序来实现查询的执行(将所有的谓词和类型转换都固定下来)。用线程的编译器把代码转化为一个共享的对象,将起链接到DBMS的进程中(类似于C++写的python库),然后调用exec函数(在一个进程中启动另一个程序执行的方法)
对于查询计划的特定部分,通过算法将这部分进行重新编译,并连接到最终的查询程序中。

生成的查询代码的组件可以调用DBMS中任何其他函数,这允许它使用与Interpreted Plan相同的组件:并发控制、检查点、索引等。

Interpreted Plan 与 Templated Plan

  1. 需要明确表中的信息,如,属性值大小等。
  2. 计算每个tuple的大小
  3. 返回tuple指针

比如对于
Select * from A where A.val=?+1


在解释的计划中, 其中get_tuple首先要获取从目录中获取表的格式,根据元组大小计算偏移量,然后返回元组的指针;eval()是遍历谓词树获取值,再获取目标属性的偏移量,根据需要进行比较操作,返回true/false。
而对于模板化的计划,已经定义好了像前面解释的计划中的获取表的格式、元组大小这些信息,按照模板执行就行了。

对查询编译性能的评估

  • Generic Iterators:通用模型
  • Optimized Iterators:对属性值有特定代码生成的模型,即,固定属性值,固定属性值大小
  • Generic Hardcoded:对谓词和泛型迭代器产生特定的代码
  • Optimized Hardcoded:直接访问元组的评估模型
  • HIQUE:对特定查询计划产生代码的评估模型

JIT编译(LLVM)

关系型操作是对查询有效的方式,但不是执行查询最有效率的方式。需要长时间进行编译C/C++ 源代码 成 可执行代码;HIQUE不支持完全的管道,它的管道会因为其他数据没有处理完而等待其他数据。


HIQUE的管道

Hyper数据库实现了JIT,用LLVM编译器去编译上面的查询计划,尽可能的将元组留存在CPU的寄存器中。核心部件是低级编程语言IR,不是所有的DBMS都需要用IR实现,LLVM可以调用C++。
它会根据管道瓶颈生成代码,但是多个core或者多个thread都不能同时在一个查询中的多个管道上运行,只能一个线程按顺序在多个管道上完成处理。但是可以安排在管道执行的先后顺序。

相关文章

  • 查询编译与代码生成

    在内存数据库中提高吞吐量的唯一方式就是减少执行指令数目。大多代码都是为了人能理解而不是单为了性能。接下来从逻辑查询...

  • 使用wasm2c反编译wasm代码

    下载wabt代码 编译wabt代码 反编译wasm代码 以反编译eosio.token.wasm为例: 会生成 e...

  • Mybatis Generator 分页查询插件开发

    官方的 Mybatis Generator 工具生成的代码中没有分页查询的功能,如果想为生成的代码添加分页查询功能...

  • 第一章绪论

    编译过程和编译程序结构 五个阶段: 词法分析 语法分析 语义分析和中间代码生成 优化 目标代码生成 编译程序的开发...

  • 编译器前端和后端

    编译器粗略分为词法分析,语法分析,类型检查,中间代码生成,代码优化,目标代码生成,目标代码优化。把中间代码生成及之...

  • gRPC java的编译

    gRPC-java代码生成器 gRPC-java的代码生成器编译需要先编译protobuf,否则会报c++源文件无...

  • 知识点OC文件生成C++文件

    生成 使用clang编译器将Objective-C代码编译成C语言代码, 并生成在一个.cpp的 C++文件中: ...

  • TypeScript Downleveling - 什么是 Ty

    下列 TypeScript 代码: 使用 tsc 编译器编译之后生成的 JavaScript 代码: 为什么字符串...

  • c++:模板

    编译器会根据代码自动生成函数。

  • 代码混淆

    LLVM编译过程: 预处理,词法分析,token,语法分析,AST,代码生成,LLVM IR,优化,生成,汇编代码...

网友评论

      本文标题:查询编译与代码生成

      本文链接:https://www.haomeiwen.com/subject/xdjcqktx.html