邮箱:oxwangfeng@qq.com
分类: 服务器与存储
2016-01-28 14:00:37
一些多机查询计算场景下,要求合并多机数据源,假设某个需求需要将数据再次计算,而计算的列不在select查询中,拿回来的多机数据源因为没有需要计算的列,就无法计算;
通过记录原来select的列数,将需要再次计算的列附加到select列中,待计算完毕后,按照原来的select列数将数据发送给客户端。
本方案应用于多机查询处理中(分布式数据库),结合数据定义配置,使用本方法能够获取到查询需要的额外列是否真实有效,结合数据散列方法优化本方法的使用。
处理流程如下图所示:
上图的处理流程解释:
Original query:原始查询,一般是用户发给数据库的查询语句;
Sytax tree:语法树,用户发送给数据库的查询语句,通过解析器生成的一个可供代码处理的逻辑结构;
Fetch select list:这个动作是获取SELECT查询语句中的查询列。
Have group:这个动作是检查SELECT查询语句中是否存在GROUP关键字。
Have order:这个动作是检查SELECT查询语句中是否存在ORDER关键字。
Select list:一个存储SELECT语句中查询列的数据结构。
Select list, [group list, order list]:修改后的查询语句格式,括弧里面的新增列,是附加到原始列后面的。
处理流程步骤:
1. 原始SQL解析成语法树结构,该语法树能够提供一个代码结构,后续处理流程会使用到这个代码结构。
2. 首先扫描SELECT查询的列,将SELECT的列存储到SELECT LIST结构中。
3. 扫描语法树查看是否有GROUP(分组)关键字存在,如果存在,需要判断GROUP分组的列在SELECT LIST中是否已经存在,如果不存在,则将GROUP分组列增加到SELECT LIST中,并将GROUP分组列附加到原查询语句的查询列尾部,并且记录下分组列在查询列中的位置。
4. 扫描语法树查看是否有ORDER(排序)关键字存在,如果存在,需要判断SELECT LIST是否已经存在ORDER排序列,如果ORDER排序列没有包含在SELECT LIST中,则将ORDER排序列放入SELECT LIST中,并且将ORDER排序列附加到查询语句尾部,标记ORDER排序列在查询语句中的位置。
经过处理流程1,2,3,4就将客户端发送给数据库的原始查询语句改写为新的查询语句,下面使用一个具体例子来说明实际处理过程。
例:
Original query(原始查询语句,客户端发送给数据库的查询语句):SELECT email FROM userInfo WHERE create_time > ‘2011-11-11’ GROUP BY name order by id desc;
syntax tree:SQL解析后的语法树(略,这是其他独立模块提供的)
Fetch select list:扫描语法树,可以发现SELECT查询的列有email,因此,将email存放到SELECT LIST。
Have group:扫描语法树,发现有GROUP关键字,分组列name不存在与SELECT LIST中,因将name放入SELECT LIST中,并且将name附加到查询列后面,这时候SQL语句为SELECT email, name FROM…,标记分组列name在查询中的位置为1(从左到右,从0开始,email位置为0,name为1)。
Have order:扫描语法树,发现有ORDER关键字,排序列为id,该列不在SELECT LIST中,因此将排序列ID附加到查询语句中,查询语句变为SELECT email, name, id FROM … ,标记排序列在查询中的位置为2。
经过一系列处理流程,那么为了实现这次查询,已经将查询重写改写为形成一个新的查询:
SELECT email,name, id FROM userInfo WHERE create_time > ‘2011-11-11’ GROUP BY name ORDER BY id DESC;
所得到的信息有:原始查询的列数,改写后的列数,分组列位置,排序列的位置。
使用处理后的SQL语句从数据存放点取回数据,根据所得到的信息,依次执行分组,排序,然后再发送的时候,按照原始查询的列数发送数据到客户端。