邮箱:oxwangfeng@qq.com
分类: 服务器与存储
2016-01-28 13:48:00
1、 技术背景
1.1 背景技术
在数据库领域中单机数据库查询的常见聚合查询MAX(求最大值)、MIN(求最小值)、SUM(求和)、AVG(求平均值)、COUNT(求记录数)在多机查询中的实现方法;本方法可以解决分布式(多机)数据库场景下,聚合查询的实现,使用本装置可以在分布式数据库上支持聚合查询的处理。
2.1 解决的技术问题
解决目前使用分库分表方案将数据分布到多机数据库实例上,不支持聚合查询问题。
本方案为了解决了分库分表后多机聚合查询聚合函数出现在having子查询中和SELECT LIST中的方法。
2.2 技术方案
根据聚合函数可能出现的两个地方,有两种不同的处理方法。
1. 聚合函数出现在Having子查询中: 一个带有聚合函数的查询命中多个查询时,处于having语句中的聚合处理,若该列与数据散列方法没有关系,如果select列中没有同样的聚合处理列,那么将聚合函数放置到select列中,并且记录下过滤条件。
2. 聚合函数出现在SELECT LIST中:聚合等价转换:如果聚合处理是avg处理,使用额外的sum和count来替代avg的处理,记录下新增select列的位置。
具体流程如下图所示:
上图中的动作名次解释:
Original query:原始查询,一般是用户发给数据库的查询语句;
Sytax tree:语法树,用户发送给数据库的查询语句,通过解析器生成的一个可供代码处理的逻辑结构;
Have function:这个动作是检查语法树中的查询列中是否有函数处理。
Avg function:查询列中的处理是否为平均值函数处理。
Other function:其他函数处理,指SUM COUNT MAX MIN。
Select list end + sum , count:AVG function 的处理,在查询列后增加SUM和COUNT。
Function list:存放函数的数据结构。
Have having:扫描语法树判断having子查询是否存在。
Function exist:检查having子查询中是否有function。
Filter list:存放having子查询过滤条件的数据结构。
执行步骤:
1. 原始SQL(original query)语句经过一个专业级的SQL解释器(sql parse),生成一个SQL语法树(syntax tree)。
2. 扫描SQL语法树中的查询列会得到两种情况(scan & have function):
非AVG(other functions)处理将函数:
如果扫描发现的函数是SUM COUNT MIN MAX等非AVG处理的函数,那么将函数类型和所在查询列的位置存放到function list中;
AVG(avg function):
如果扫描发现的函数是AVG求平均值的函数,那么除了将函数类型和所在查询列的位置存放到function list中,同时将对应的COUNT和SUM附加到查询列中(如果查询列中没有AVG计算列的COUNT和SUM),记录下COUNT和SUM的位置,存放到和AVG一起的function list中。
3. 扫描having子查询中出现的函数(have having):
如果发现有having子查询:扫描function list查看函数是否已经存在,如果不存在,将函数追加到SELECT LIST中,并且存放到function list;记录下having过滤条件存储到filter list中。
经过123的处理步骤,可以得到一个全新的查询语句,具体列子如下:
例:
假设一张表,包含列:Id, name, sex, age, city, mobile,其中ID是主键。
original query(原始查询):SELECT city, avg(age) FROM acid GROUP BY city HAVING(count(id) > 100000)
原始查询含义:这个查询有两个聚合函数,avg(age)城市人口平均年龄,count(id)城市人数,还隐含了城市人数大于10万的条件。
syntax tree:SQL解析后的语法树(略,这是其他独立模块提供的)
have function:扫描语法树中对应的原始代码部分(SELECT city, avg(age) FROM),发现有AVG求平均值的处理,按照等价变换的方法,需要使用SUM(AGE)和COUNT(AGE),并且查询列中没有这两个处理,因此,在查询尾部附加上SUM(AGE), COUNT(AGE),并且将AVG(AGE)函数类型和位置存放到,function list中,并且SUM(AGE), COUNT(AGE)也一并存放到function list中,标记出与AVG的关系。
SQL改写为:SELECT city, avg(age),SUM(age), COUNG(age) FROM acid GROUP BY city HAVING(count(id) > 100000)
记录信息为:对查询列位置为1的列做AVG平均值计算,AVG已经等价替换为SUM和COUNT,因此记录信息还包含SUM和COUNT的位置。
Have having:扫描语法树发现有having子查询,检查子查询中的函数发现有COUNT(id)函数,根据have function中的处理方式,因为是COUNT查询,所以查询function list发现不存在COUNT(ID)的函数,因此将COUNT(ID)附加到查询列中,并且存储到function中;改having子查询还带有过滤条件>100000,将这个条件存放到filter list中,标记上查询列中COUNT(ID)计算完成后,要进行过滤。
SQL改写为:SELECT city, avg(age),SUM(age), COUNG(age),COUNT(id) FROM acid GROUP BY city
记录信息为:对COUNT(id)位置的列做COUNT计算,并且计算完成后还要做大于10万的过滤,记录下原始列为2,改写后的列为5。
使用处理后的SQL查询从数据库取回数据,首先根据分组(分组处理是一个独立的模块)将SUM(age), COUNG(age),COUNT(id)计算出来;每一行的AVG(age)都使用计算出来的SUM(age)/COUNT(age)来填充;最后将COUNT(id)做大于10万就完成了计算,然后根据原始列记录数据发现是2,将0,1两列数据发送给客户。
2.3 名词解释
SELECT LIST:SQL查询语句SELECT id, name, count…. FROM之间的以逗号隔开的部分是SELECT LIST。
HAVING子查询:HAVING是标准SQL关键字,HAVING(EXPR)括号中的EXPR表示子查询,也就是HAVING子查询。
SQL节点:分布式数据库中处理SQL的节点。
数据节点:分布式数据库中存储数据的节点。
中间件:位于数据库和应用之间的一个程序装置。