如题所述
一些多机查询计算场景下,要求合并多机数据源,假设某个需求需要将数据再次计算。
计算的列不在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]:修改后的查询语句格式,括弧里面的新增列,是附加到原始列后面的。
原始SQL解析成语法树结构,该语法树能够提供一个代码结构,后续处理流程会使用到这个代码结构。首先扫描SELECT查询的列,将SELECT的列存储到SELECT LIST结构中。
扫描语法树查看是否有GROUP(分组)关键字存在,如果存在,需要判断GROUP分组的列在SELECT LIST中是否已经存在,如果不存在,则将GROUP分组列增加到SELECT LIST中,并将GROUP分组列附加到原查询语句的查询列尾部,并且记录下分组列在查询列中的位置。
扫描语法树查看是否有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语句从数据存放点取回数据,根据所得到的信息,依次执行分组,排序,然后再发送的时候,按照原始查询的列数发送数据到客户端。
分库分表后能够支持复杂查询,如GROUP、ORDER等等;数据存储节点参与计算,相比直接把数据全部查询到应用程序中进行计算,具有更小的网络开销,更快的计算速度。
在多机查询中,不需要应用程序参与查询计算;通过关系代数等价变化的方式,重写查询语句,让数据节点参与查询计算的方式,相比常规方案性价比要高。