高性能查询处理技术
DM7采用基于代价的查询优化策略,使用了多趟处理策略,结合面向堆栈的虚拟机执行器,并借助重用等优化手段,争取达到最优的查询效果。
查询语句分析优化过程并非一蹴而就,而是分多个阶段进行变换处理,直至最终生成物理查询计划。
PARSE:进行语法检查,将原始语句转换为对应语法树。
PHASE A:进行语义分析,将标识符翻译为对应字典对象。
PHASE B:关系变换。
1、按照规则将语法树变换为关系(REL)树;
2、处理子查询,将IN、EXISTS查询变换为半连接(SEMI JOIN);
3、处理子查询的相关性,将相关性去除,变为与引用表的连接(JOIN)。
PHASE C:利用统计信息进行代价优化。
1、对于单表查询,选择合适索引。
2、对于多表链接,选择连接顺序,选择物理连接操作符
PHASE E:表达式优化
1、重用语句中相同表达式,避免重复计算
2、尽量选择批量指令执行计算,减少反复调用的代价
PHASE G:并行优化,构造并行操作符,使用多线程处理水平分区表的查询。
DM7查询优化器利用优化规则,将所有的相关子查询变换为等价的关系连接,从而取消查询的嵌套关系。
例如:
from c_order
where exists (
select *
from c_order_line
where o_id = ol_o_id
and ol_quantity > 10
)
上面的关系树就会被转化为与其等价的如下语句(伪SQL)的关系树:
from c_order A semi_join (
select B.ROWID
from c_order_line, c_order B
where B.o_id = ol_o_id and ol_quantity > 10
group by B.ROWID
) on A.ROWID = B.ROWID
对于半连接或其中嵌套的因去除相关型而引入的连接,可以基于一定的规则进行优化。如上例中关系树可再被优化为如下语句的关系树:
from c_order semi_join c_order_line
where A.o_id = ol_o_id and ol_quantity > 10
相关子查询的平坦化,极大降低了代价优化的算法复杂程度,使得优化器可以更容易地生成较优的查询计划。
DM7在之前版本虚拟机的基础上,为进一步完善了功能、提高执行效率,做了如下改进。
1. 采用以字长为分配单位的标准堆栈,提高空间利用率,充分利用CPU的2级缓存,提升性能。
2. 增加栈帧概念,方便实现函数/方法的跳转,为PL/SQL脚本的调试提供基础。
3. 增加内存运行堆的概念,实现对象、数组、动态的数据类型存储。
4. 采用面向栈的表达式计算模式,减少虚拟机代码的体积、数据的移动。
5. 重新定义指令系统,增加对对象、方法、参数、堆栈的访问,便于实现PL/SQL的执行。
而实现的虚拟机结构如下图所示。
DM7面向堆栈的虚拟机执行器,可以在指令与操作符间平滑地切换执行,也能够轻松地实现过程/函数的调用。借助简单高效的指令系统,以及直观快速的堆栈数据传输机制,可以有效提升SQL脚本或过程/函数的执行效率。
SQL语句从分析、优化到实际执行,每一步都需要消耗系统资源。查询计划的重用,可以减少重复分析操作,有效提升语句的执行效率。DM7采用参数化常量方法,使得常量值不同的查询语句,同样可以重用查询计划。经此优化后的计划重用策略,在应用系统中的实用性明显增强。
查询结果集同样可以缓存。相同的查询语句,如果涉及表数据没有变化,则可以直接重用缓存的结果集。查询结果缓存,在数据变化不频繁的OLAP应用模式,或存在大量类似编目函数查询的的应用环境下有非常良好的性能提升效果。
在服务器端实现结果集缓存,可以在提升查询速度的同时,保证缓存结果的实时性和正确性。