SQL解析及体会
2016-01-14 03:26
197 查看
最近在搞一个项目需要对实时流数据进行数据关联,直接查询数据库处理效率太低,直接访问redis也不太理想,一个数据要进行10次左右查询,每秒多则几百条数据,就要进行几千次查询;若是实时程序挂了,还需要进行批处理,一旦批处理,每秒要处理的数据就更多了,为了提升效率,就采用内存缓存+redis的模式,因为这些数据是用户访问网页的数据,数据具有连贯性,上一次的查询结果短时间内还用得到,所以内存缓存可以极大地减少从redis查询的次数。
最开始想到的是根据输入的字段,先到内存中查询数据,查不到然后到redis查询,查回来后放到内存中进行缓存。数据关联的逻辑是在代码中写死的,比如有[a,b,c]字段,需要从多个数据源ds_a,ds_b,ds_c中关联出[a1,b1,c1]字段。代码大致如下:
写代码的时候,相关的数据都封装成了具有固定属性的对象,但是写完之后麻烦就来了,此前没做过类似用户行为分析的东西,客户的统计需求变化很快,每新增一个统计,或者变换一个统计口径,我们都需要修改代码,然后编译,重新部署,代价很大;于是就萌生了将数据的关联逻辑通过配置来实现的想法,关联逻辑能实现动态更新,这样就不用成天改代码了。我们想了好久,希望数据的关联逻辑能够像SQL那样精炼易懂,同时也足够灵活。
说了半天才进入正题O(∩_∩)O~,请原谅用了这么大篇幅去交代背景。因为我写这些是为了记住自己这回的想法。
既然想通过类似SQL的表达方式来描述逻辑,那么就涉及如何解析SQL,并完成数据关联的逻辑。如如下SQL:
select a1 from ds_a on key=a where col1=xxx;
为了承载以上逻辑,我设计了下面的类和接口:
为了从SQL构建Rule,就需要对SQL字符串进行解析,想了好久,尝试了很多次,首先通过正则表达式提取出fileds,table,key,condition字符串
前面3个字段还好处理,关键是condition字符串到 ICondition的映射,通过上述表达式已经提取到了condition字符串 col1=xxxx,如果只是这么简单也还好处理,split一下就可以得到相依的key和value,从而构造Condition作为rule的ICondition,但又想要支持更为复杂的condition,比如:
这时候犯难了,又经过一番折腾最终实现了,其中过程就不详述了,只写下最终的思路:
1、首先对condition进行分词,将每一个不可分割的元素提取到数组中。
2、优先处理阔号,首先将括号的内容处理成ICondition,如果阔号存在嵌套,则最先处理里面的括号,把括号中的内容提取出来构建ICondition,由于这部分内容已经不包含括号,所以处理起来相对简单,我将不带括号的condition叫简单condition,通过这样的方式逐层剔除括号,最终转化成针对一个个简单condition的处理;
3、简单condition的处理要从高优先级运算到低优先级运算顺序处理,对于简单condition无法只剩下如下运算符: =,and,or,他们的优先级为 =优先于and, and 优先于 or。所以先把=号两侧的操作数构建成ICondition,然后再把and两侧的操作数构建成ICondition,然后才是or。
由于时间仓促,相关代码只能来日再补上,上面贴的代码只是为了示意,并非真实代码。
最开始想到的是根据输入的字段,先到内存中查询数据,查不到然后到redis查询,查回来后放到内存中进行缓存。数据关联的逻辑是在代码中写死的,比如有[a,b,c]字段,需要从多个数据源ds_a,ds_b,ds_c中关联出[a1,b1,c1]字段。代码大致如下:
a1 = ds_a.get(a as id) .get(colname of a1); b1 = ds_b.get(b as id).get(colname of b1); c1 = ds_c.get(c as id).get(colname of c1);
写代码的时候,相关的数据都封装成了具有固定属性的对象,但是写完之后麻烦就来了,此前没做过类似用户行为分析的东西,客户的统计需求变化很快,每新增一个统计,或者变换一个统计口径,我们都需要修改代码,然后编译,重新部署,代价很大;于是就萌生了将数据的关联逻辑通过配置来实现的想法,关联逻辑能实现动态更新,这样就不用成天改代码了。我们想了好久,希望数据的关联逻辑能够像SQL那样精炼易懂,同时也足够灵活。
说了半天才进入正题O(∩_∩)O~,请原谅用了这么大篇幅去交代背景。因为我写这些是为了记住自己这回的想法。
既然想通过类似SQL的表达方式来描述逻辑,那么就涉及如何解析SQL,并完成数据关联的逻辑。如如下SQL:
select a1 from ds_a on key=a where col1=xxx;
为了承载以上逻辑,我设计了下面的类和接口:
public class Rule { String table; List<String> fields; String key; ICondition cond; } interface ICondition { boolean filter(Map row); } public class Condition implement ICondition { String key; String value; @Overide public boolean filter(Map row){ return row[key] == value; } } public class Conditions implement ICondition { List<ICondition> conds; String operation; //"and" 或者 "or" @Overide public boolean filter(Map row){ if(operation == "and") return !has(false); else return has(true); } }
为了从SQL构建Rule,就需要对SQL字符串进行解析,想了好久,尝试了很多次,首先通过正则表达式提取出fileds,table,key,condition字符串
.*select (.*) from (.*) on (.*) where (.*)
前面3个字段还好处理,关键是condition字符串到 ICondition的映射,通过上述表达式已经提取到了condition字符串 col1=xxxx,如果只是这么简单也还好处理,split一下就可以得到相依的key和value,从而构造Condition作为rule的ICondition,但又想要支持更为复杂的condition,比如:
col1 = xxx and ( col2=xxx or col3=xxx )
这时候犯难了,又经过一番折腾最终实现了,其中过程就不详述了,只写下最终的思路:
1、首先对condition进行分词,将每一个不可分割的元素提取到数组中。
2、优先处理阔号,首先将括号的内容处理成ICondition,如果阔号存在嵌套,则最先处理里面的括号,把括号中的内容提取出来构建ICondition,由于这部分内容已经不包含括号,所以处理起来相对简单,我将不带括号的condition叫简单condition,通过这样的方式逐层剔除括号,最终转化成针对一个个简单condition的处理;
3、简单condition的处理要从高优先级运算到低优先级运算顺序处理,对于简单condition无法只剩下如下运算符: =,and,or,他们的优先级为 =优先于and, and 优先于 or。所以先把=号两侧的操作数构建成ICondition,然后再把and两侧的操作数构建成ICondition,然后才是or。
由于时间仓促,相关代码只能来日再补上,上面贴的代码只是为了示意,并非真实代码。
相关文章推荐
- mysql 更新多条id键值相同记录中的最新(最后一条)记录
- Spark SQL性能优化
- Mongodb 笔记07 分片、配置分片、选择片键、分片管理
- NoSQL and Redis
- 信息安全聚合 Sec-News 的重构之路
- 在php中设置session用memcache来存储的方法总结
- 在Linux系统上同时监控多个Oracle数据库表空间的方法
- mysql 数据库死锁原因及解决办法
- mysql数据库锁的产生原因及解决办法
- 批量 kill mysql 中运行时间长的sql
- 优化innodb_log_file_size参数
- excel数据导入数据库
- tomcat&memcached实现session共享
- Redis源码安装 CentOS7
- IOS开发之_SQLite
- MySQL 数据库主从复制架构
- 通过读取excel文件生成sql语句
- oracle数据中删除数据时提示“记录被另一个用户锁住”
- 配置solr的数据库引擎的core时的异常
- node-oracledb 连接 RAC集群