文档章节

自己动手写SQL查询引擎-总篇

无毁的湖光-Al
 无毁的湖光-Al
发布于 2017/03/23 10:58
字数 1053
阅读 1951
收藏 63

自己动手写SQL查询引擎-总篇

本篇Blog在总体层面介绍了SQL查询引擎Rider的功能及设计,其细节部分将会在后面的篇章中一一道来。

起因

笔者在实际工作中经常需要解析文件,每次文件稍有变化,都得拷贝粘贴一堆代码。
于是就想着能不能做一个通用的服务,通过配置的方式解析文件。

配置通用

最通用的方法就是自己定义一个文件描述语言,用语言去描述文件的组织结构。但如果自己定义一套新的语法,学习成本则太高。

基于SQL

于是就想到了数据库,数据库是通过create table来表示文件格式的,且通过sql来查询底层数据。
这个create table和select操作和我的需求match,就这样SQL查询引擎Rider诞生了。

Rider代码灵感

Rider借鉴了不少项目的代码,例如MySql协议部分借鉴了Corbar。
Sql解析部分借鉴了h2database,derby等。
文件解析部分源于笔者写的大部分文件解析业务代码。
在此向上述优秀的开源代码致敬。

SQL查询引擎Rider

Rider是一个基于Netty通讯框架的纯java写的Server,其不依赖其它任何服务。其主要功能如下图所示:
rider_func
(1)Rider基于MySql协议和用户交互,用户可以使用mysqlClient、jdbc以及odbc等对Rider发送SQL命令
(2)Rider支持select join where condition、create table等语法
(3)Rider支持MyBatis

Rider总体设计

rider_archetype
这里Rider主要分四层:
(1)MySql协议层,负责通过MySql协议与用户的交互,详情可见:
https://my.oschina.net/alchemystar/blog/834150
(2)Sql解析层:负责对select以及create table等语法的解析
(3)Access层:提供游标Cursor这个概念,供Sql解析层去遍历记录
(4)Storage层:对很多中文件格式进行解析,统一封装成游标Cursor给上层调用,
当前Storage还包含了视图的概念,这是Rider另一个特性,在后面的篇章中阐述。

Rider查询表的原理

下图是Rider查询表的原理,
rider_execute
Rider查询表的原理是通过将文件中所有记录读取出来并通过where或者join条件进行遍历,从而筛选出对应的记录。
对于多表查询,则是通过将多个文件中的记录进行笛卡尔积的便利来筛选记录。

Rider文件配置的通用性

文件列位置不定

详细描述:文件A,文件B包含相同的数据,只是列的位置不一样,例如: 文件A:

1,lancer,lancer_comment   
2,rider,rider_comment

文件B:

1.lancer_comment,lancer    
2,rider,rider_comment  

在Rider中只需要在不同的schema中建立两张相同的表t_test,就可以在应用端代码复用,底层细节的Rider全包了。

use schemaA;
create table t_test( 
  id BIGINT comment 'id test ', 
  name VARCHAR comment 'name',
  extension VARCHAR comment 'extension' 
)Engine='archer' SEP=',' comment='just for test';
use schemaB;
 create table t_test( 
  id BIGINT comment 'id test ', 
  extension VARCHAR comment 'extension' /*此处列位置调整*/
  name VARCHAR comment 'name',
)Engine='archer' SEP=',' comment='just for test'

这样客户端就可以不考虑文件列的位置了。

文件格式不固定

考虑到三个文件,文件A、文件B以及文件C 文件A,以,分隔:

1,lancer,lancer_comment   
2,rider,rider_comment

文件B,以|分隔:

1|lancer|lancer_comment   
2|rider|rider_comment

文件C,XLSX格式

use schemaA;
create table t_test( 
  id BIGINT comment 'id test ', 
  name VARCHAR comment 'name',
  extension VARCHAR comment 'extension' 
)Engine='archer' SEP=',' comment='just for test';
use schemaB;
 create table t_test( 
  id BIGINT comment 'id test ', 
  name VARCHAR comment 'name',
  extension VARCHAR comment 'extension' 
)Engine='archer' SEP='|' /*此处分隔符调整为|*/  comment='just for test'
use schemaC;
create table t_test( 
  id BIGINT comment 'id test ', 
  name VARCHAR comment 'name',
  extension VARCHAR comment 'extension' 
)Engine='XLSX'/*此处引擎调整为xlsx*/;

这样客户端也不需要考虑文件格式了。
如果上述不直观的话,可以如下图所示:
rider_file

Rider性能

文件解析速度4W行/s,其只和java本身文件IO性能相关。

Rider截图

rider_example

github链接

https://github.com/alchemystar/Rider

码云链接

http://git.oschina.net/alchemystar/Rider
##原文链接 https://my.oschina.net/alchemystar/blog/865237

© 著作权归作者所有

无毁的湖光-Al

无毁的湖光-Al

粉丝 430
博文 30
码字总数 51882
作品 0
浦东
后端工程师
私信 提问
加载中

评论(18)

无毁的湖光-Al
无毁的湖光-Al 博主

引用来自“极客小子”的评论

项目找创业合伙人,有市场的项目,要求会安卓和java,有兴趣可以来了解了解q983270700

@极客小子暂时不考虑 谢谢
雨林星空
雨林星空

引用来自“乌龟壳”的评论

为毛不做成数据库插件

引用来自“无毁的湖光-Al”的评论

😄当时没想到这一点,就直接做成了server
:bowtie:
无毁的湖光-Al
无毁的湖光-Al 博主

引用来自“丛林迷雾”的评论

引用来自“丛林迷雾”的评论

好厉害,@无毁的湖光-Al 有一个问题啊,一次性把文件数据全部取出来,会内存溢出啊,我们项目前段时间遇到一大片溢出全部是因为再生成、上传文件过程中对文件中的数据处理过程中溢出,原因就是文件过大把数据都存再list中了。

引用来自“无毁的湖光-Al”的评论

当前的设计比较简单,就是把文件全部捞去到内存里面。后续开发的话,会将当前游标指向的下N条数据捞取到内存里面出来,然后将游标指向的前面所有的数据丢弃。这样可以解决溢出问题,不过游标回溯就麻烦了。说白了就是一个缓冲区设计哈~。更复杂的文件缓冲层设计可以参照MySql里面的缓冲区设计。这些LRU之类的丢弃策略应该是老生常谈了~
坐等大神开发成完善架构哈哈哈,我目前用简单粗暴的方式做了个文件处理工具,只接受几种标准文件格式,文件读取也是比较基础的方式,处理一条释放一条
你这个思路很6了,值得学习

回复@丛林迷雾 : 多谢鼓励 哈哈
丛林迷雾
丛林迷雾

引用来自“丛林迷雾”的评论

好厉害,@无毁的湖光-Al 有一个问题啊,一次性把文件数据全部取出来,会内存溢出啊,我们项目前段时间遇到一大片溢出全部是因为再生成、上传文件过程中对文件中的数据处理过程中溢出,原因就是文件过大把数据都存再list中了。

引用来自“无毁的湖光-Al”的评论

当前的设计比较简单,就是把文件全部捞去到内存里面。后续开发的话,会将当前游标指向的下N条数据捞取到内存里面出来,然后将游标指向的前面所有的数据丢弃。这样可以解决溢出问题,不过游标回溯就麻烦了。说白了就是一个缓冲区设计哈~。更复杂的文件缓冲层设计可以参照MySql里面的缓冲区设计。这些LRU之类的丢弃策略应该是老生常谈了~
坐等大神开发成完善架构哈哈哈,我目前用简单粗暴的方式做了个文件处理工具,只接受几种标准文件格式,文件读取也是比较基础的方式,处理一条释放一条
你这个思路很6了,值得学习
无毁的湖光-Al
无毁的湖光-Al 博主

引用来自“sameLuo”的评论

感觉很类似于spark sql啊

@sameLuo 是呀 都是支持SQL语法 :)
sameLuo
sameLuo
感觉很类似于spark sql啊
无毁的湖光-Al
无毁的湖光-Al 博主

引用来自“Ambitor”的评论

笛卡尔积😂 全部load。。这两个问题很大哦。数据量大了能出来嘛😆
后续可以考虑下索引啊。
sql解析这块也可以借鉴druid代码~
总之还是厉害的,加油~

@Ambitor druid太复杂 自己弄的可定制化。这就是个查询文件 索引没必要 可以类比成mapreduce
Ambitor
Ambitor
笛卡尔积😂 全部load。。这两个问题很大哦。数据量大了能出来嘛😆
后续可以考虑下索引啊。
sql解析这块也可以借鉴druid代码~
总之还是厉害的,加油~
无毁的湖光-Al
无毁的湖光-Al 博主

引用来自“丛林迷雾”的评论

好厉害,@无毁的湖光-Al 有一个问题啊,一次性把文件数据全部取出来,会内存溢出啊,我们项目前段时间遇到一大片溢出全部是因为再生成、上传文件过程中对文件中的数据处理过程中溢出,原因就是文件过大把数据都存再list中了。
当前的设计比较简单,就是把文件全部捞去到内存里面。后续开发的话,会将当前游标指向的下N条数据捞取到内存里面出来,然后将游标指向的前面所有的数据丢弃。这样可以解决溢出问题,不过游标回溯就麻烦了。说白了就是一个缓冲区设计哈~。更复杂的文件缓冲层设计可以参照MySql里面的缓冲区设计。这些LRU之类的丢弃策略应该是老生常谈了~
丛林迷雾
丛林迷雾
好厉害,@无毁的湖光-Al 有一个问题啊,一次性把文件数据全部取出来,会内存溢出啊,我们项目前段时间遇到一大片溢出全部是因为再生成、上传文件过程中对文件中的数据处理过程中溢出,原因就是文件过大把数据都存再list中了。
报表性能优化方案之单数据集分页SQL实现层式报表

1、概述 我们知道,行式引擎按页取数只适用于Oracle,mysql,hsql和sqlserver2008及以上数据库,其他数据库,如access,sqlserver2005,sqlite等必须编写分页SQL。 下面以Access数据库为例介绍...

九月你好123
2015/09/07
63
0
Innodb存储引擎

特点:支持事务。锁定机制的改进,Innodb改变了MylSAM的锁机制,实现了行锁。实现外键。.frm文件来存放结构定义相关的元数据,但是表数据和索引数据是存在一起的,每个表单独存放还是表存放在...

宏强
2017/03/07
0
0
hibernate操作数据库总结

这篇文章用于总结hibernate操作数据库的各种方法 一、query方式 1、hibernate使用原生态的sql语句执行数据库查询 有些时候有些开发人员总觉得用hql语句不踏实,程序出现了错误,就猜测因为不...

小思绪跌跌撞撞仰望天空
2016/08/18
18
0
一条sql语句在mysql中是如何执行的

概览 最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的...

木木匠
03/26
5.2K
14
「mysql优化专题」这大概是一篇最好的mysql优化入门文章(1)

【mysql优化专题】:本专题全文围绕mysql优化进行全方位讲解,本篇为优化入门篇,让大家知道为什么要优化,究竟在优化什么。喜欢的朋友可以关注收藏。 优化,一直是面试最常问的一个问题。因...

java进阶架构师
2017/11/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Experts say the weaker pound is drawing investors to the UK tech sector

UK tech companies secured a record £5.5bn in foreign investment in the first seven months of this year, research shows. This was more than the amount invested per capita in th......

wowloop
27分钟前
5
0
Add support for Android 9-patch images in BorderImage

The 9-patch image implementation in Qt Quick Controls 1 is an internal implementation detail of the Android style. It cannot handle .9.png image files out of the box, but takes ......

shzwork
32分钟前
4
0
c/c++日期时间处理函数小结

日期时间处理函数: 日期时间转为字符串 strftime/std::put_time 字符串解析成日期时间 strptime/std::get_time 时间结构转换:time_t->tm localtime:time_t->tm 时间结构转换:tm->time_t ...

chuqq
36分钟前
5
0
Apache Flink 进阶入门(二):Time 深度解析

前言 Flink 的 API 大体上可以划分为三个层次:处于最底层的 ProcessFunction、中间一层的 DataStream API 和最上层的 SQL/Table API,这三层中的每一层都非常依赖于时间属性。时间属性是流处...

大涛学长
37分钟前
4
0
创龙基于Xilinx Artix-7系列FPGA处理器

SOM-TLA7是一款由广州创龙基于Xilinx Artix-7系列FPGA自主研发的核心板,可配套广州创龙Artix-7开发板使用。核心板尺寸仅70mm*50mm,采用沉金无铅工艺的10层板设计,专业的PCB Layout保证信号...

Tronlong创龙
43分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部