您的位置:首页 > 数据库

SQL解析及体会

2016-01-14 03:26 197 查看
最近在搞一个项目需要对实时流数据进行数据关联,直接查询数据库处理效率太低,直接访问redis也不太理想,一个数据要进行10次左右查询,每秒多则几百条数据,就要进行几千次查询;若是实时程序挂了,还需要进行批处理,一旦批处理,每秒要处理的数据就更多了,为了提升效率,就采用内存缓存+redis的模式,因为这些数据是用户访问网页的数据,数据具有连贯性,上一次的查询结果短时间内还用得到,所以内存缓存可以极大地减少从redis查询的次数。

最开始想到的是根据输入的字段,先到内存中查询数据,查不到然后到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。

由于时间仓促,相关代码只能来日再补上,上面贴的代码只是为了示意,并非真实代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql分词