解析sql后代码会生成一个action list,来保存之前的解析结果。
action list如下:
action1 a1>
action2 b2<
action3 action1&&action2
接下来,就是将数据库中取得的所有的数据按照action1-》action2-》acton1&&action2的流程进行运算,
将结果为true的数据保留下来。
上述处理如果是少量数据的话,可能没有什么影响,如果涉及到大量数据的情况下,会比较耗时。
其实上面的运算只需判断action1是否为true,如果action1为false,则直接返回false即可。总结如下:
---------------------------------------------------------------------------------------------
a&&b-》只要a为false,或者b为false,整个表达式返回false
a||b-》只要a为true,或者b为true,整个表达式即返回true
---------------------------------------------------------------------------------------------
基于上面的想法,action list还需要转换成类似下面2叉数,
这样只要计算一个叶子节点,然后按照上面的想法,就可减少运算的步骤。
——————————action4——————
| |
————action3————— action5
| |
action1 action2
------------------------------------------------------------------------------
最优情况下,
按照上面的算法更新后,一个简单的10万条sql查询加快5倍左右。
此外
2叉树的分配也很重要,我现在是默认先生成书的左叶子节点,然后生成树的右叶子节点。这样最恶劣的情况下,
可能都需要先算左叶子节点,然后再算右叶子节点。。。。。这个偶还需要再考虑一下具体的优化方案。。。
actionlist转2叉树的处理如下:
--------------------------------------------------------------------------------------------
ActionTreeNode rootNode = new ActionTreeNode();
ArrayList<ActionTreeNode> stack = new ArrayList<ActionTreeNode>();
while(list.size() != 0) {
Action action = list.remove(0);
if(action.mAction == Action.SQL_ACTION_OR
||action.mAction == Action.SQL_ACTION_AND) {
if(stack.size() < 2) {
return null;
}
ActionTreeNode leftAction = stack.remove(stack.size()-1);
ActionTreeNode rightAction = stack.remove(stack.size()-1);
rootNode = new ActionTreeNode();
rootNode.leftChild = leftAction;
rootNode.rightChild = rightAction;
rootNode.action = action;
stack.add(rootNode);
} else {
ActionTreeNode node = new ActionTreeNode();
node.action = action;
stack.add(node);
}
}
--------------------------------------------------------------------------------------------
PS:
基于XML的数据库的开源代码有很多,比如BaseX神马的,俺写的代码肯定没有办法和它们比,
这个只属于兴趣爱好~~。如果有大牛路过~~,也请留下联系方式,俺也好请教请教。
\^o^/