论文阅读:Designing an Open Framework for Query Optimization and Compilation
TL;DR: LingoDB是一个用MLIR构建的实验室数据库,支持MLIR的原有特性,未来可期
VLDB 22的论文,作者团队来自TUM(德国慕尼黑工业大学)
项目官网:https://www.lingo-db.com/
文章下载地址:p2389-jungmair
LingoDB是一个基于MLIR开发的数据库项目,其底层存储使用Apache Arrow实现,将数据库的各类Query转为方言(Dialect)中的不同算子(Operator),通过不同层级中间代码转换,完成执行计划从逻辑计划向物理计划转化
直观上翻译:一个用于查询编译和优化的开放框架(即LingoDB),说明可以在这个平台上实现想要数据库优化和编译的特性🧐
更新记录:
2025.7.10 结合这一年的经历,增加些内容
技术背景
MLIR(Multi-Level Intermediate Representation)是由 Google 发起的一个编译器基础设施项目,其目标是为多样化硬件和高层语言的编译优化提供统一框架,目前是 LLVM 项目的子项目之一。
其存储结构使用的是Apache Arrow,是一个采用列式内存格式,用于跨平台、跨语言高效数据处理的开源项目
Github仓库情况
在Github开源了项目的代码:lingo-db
截至到2024.7.26,Star的数量为198
截至到2025.7.10,Star的数量为264
正文快速浏览
Section1: 日常介绍(讲故事)🤐
Section2: 我们要站在巨人的肩膀上开发,而LLVM就是这个巨人的肩膀,可以帮助我们构建LingoDB这个开放的平台😄
Section3: 介绍MLIR这个强大的工具(怎么感觉这介绍MLIR的部分要比MLIR Tuotrial写的要好😅),讲了IR,Dialcect,Pass(Transform)这三个部分
Section4:将SQL转为MLIR架构,进而实现端到端😲(通过编写MLIR Dialect实现)
用户只管用就行了,开发者考虑的就多了😆
Section5:SQL -> MLIR的Dialect的编写
相关源码(Op和Interface)可以在include/mlir/Dialect下面找到:
写了4种Dialect:
relalg(处理关系代数运算),db(处理数据类型与数据基本运算),dsa(数据库表,哈希表以及索引建立),util(杂项,比如Tuple的操作)
Table1的实现可见include/mlir/Dialect/RelAlg/IR/RelAlgOps.td
Table2的实现可见include/mlir/Dialect/DB/IR/DBOps.td
Section6:流程概览
有一张足够说明流程的全部细节的图:
将SQL,Pytorch模型转为MLIR,通过MLIR Dialect转换变为LLVM IR,最后读取Apache Arrow文件实现数据操作
Section7,8:与其他数据库的对比(我没啥兴趣,大伙们感兴趣的可以自己下载论文看🤔)
Section9:可扩展性
用MLIR最大的优势在于,可以与PyTorch或TensorFlow框架对接,于是我们就见到了在数据库里跑模型的情况:
数据库里可以跑模型?这可太酷了🤩~~(Wait,我明明有显卡,为什么要在数据库里面跑?)~~
Note:这部分内容,目前在LingoDB的文档中并未提及
Section10:未来展望
- 多线程运行(使用OpenMP相关的Dialect)
- 分布式运行(需要写Dialect支持MPI或RDMA)
- 异构计算
Section 11: 结语
实现细节整理
LingoDB通过方言(Dialect)的逐层降级(Lowering)可以将SQL,Pytorch代码转为可执行代码,下面将展示代码转换流程:
第一步是将SQL与PyTorch代码,转为以MLIR形式的抽象逻辑代数与元组操作(relalg),数据库杂项操作(db),数学运算(atith),在这其中可以制定查询优化(Query Opt)的方案实现MLIR代码逻辑的优化
借助MLIR的改写(Rewrite)机制,可以实现
- 代码简化(Simplification)合并冗余逻辑和消除无效分支
- 解嵌套 (Unnesting),将嵌套查询(如子查询)转换为扁平化的连接操作
- 下推 (Pushdown),将复杂条件拆分为更小的过滤(filter)单元的同时,调整操作顺序,使过滤和投影(Project)尽早执行,从而减少后续处理的数据量
- 连接排序 (Join Ordering),根据MLIR分析表间关系,设定动态规划或启发式算法生成合适的Join顺序
- 物理优化 (Physical Opt),选择算子的物理实现方式(如 Hash Join、Sort-Merge Join)
第二步实现逻辑代数的转化(lower-relalg),将抽象的逻辑代数转为具体的逻辑代数的MLIR实现(dsa)
第三步实现数据库杂项操作与数学运算的转换(lower-db,lower-dsa),将这两部分转为机器友好的MLIR实现(程序控制流scf)
最后将MLIR代码转为LLVM IR,借助LLVM的JIT运行框架完成JIT编译,读取Apache Arrow文件,实现数据的读取操作
实验结果
LingoDB用于查询优化的代码要少于DuckDB和NoisePage
而在编译时间上,因为MLIR的编译机制的原因,编译时间会高于Hyper数据库
而在TPC-H SF1数据集上,运行速度要高于Hyper于DuckDB,特别是在Q2,Q6,Q11上
总结
用MLIR写数据库,只能说意思,但感觉实用性不大:我为什么不直接用LLVM实现呢?😐
同样,多线程,分布式运行这两个Feature,直接用C++(Even Rust)实现会不会更加省事情🤐MLIR Dialect也不是能现学现用的东西
异构计算用MLIR确实有优势——那我为什么不用LLVM呢?😆
按我目前浅薄的理解:LLVM IR太底层,一些复杂操作(矩阵运算)不如MLIR方便——嗯,这可能是个不错的理由
实际情况是:
虽然LLVM相对简单,但仍然是相对的,比起高级语言来说手写LLVM IR仍有不低的复杂度。比如说实现一个简单的for循环或者分支语句,仍需要类似汇编的跳转指令。
可以看看这篇文章,解决了我不少困惑:查询编译综述
还有,我为什么要在数据库里跑机器学习?😂受限于算力,短期内应该不存在这种需求
既然VLDB 22收了,想必有其中的道理,可以再蹲个后续
2025.7.10补充
该项目的最大优点是与MLIR生态融合,这有利于AI与数据库生态系统融合,而优化中的“逐层下降”的理念,也让查询优化的边界更清晰,实现更可控,也有利于UDF(User Define Function)的实现。
但使用MLIR无疑提高了数据库的开发门槛,深度参与要求开发者横跨数据库系统与编译器技术(MLIR Dialect, LLVM)两大领域,需要处理好开发效率和可维护性之间的平衡关系