概述
In-Memory中的深度矢量化技术(Deep Vectorization),可以将每个SQL运算符内部的物理运算符流水线化,并使用SIMD对其进行矢量化,从而实现对复杂SQL运算符的优化处理。默认情况下,该特性处于启用状态,控制参数为INMEMORY_DEEP_VECTORIZATION,当然您也可以将其设置为false来禁用此特性。
深度矢量化技术是一个基于SIMD的框架,它能够支持查询计划中高级查询运算符的矢量化。该框架包括SIMD、硬件加速,以及流水线执行等诸多优化技术。
关于SIMD
要了解深度矢量化技术,首先需要了解什么是SIMD。
在计算机体系结构中,主要有SISD、SIMD、SIMT、MISD、MIMD等几种分类。
SISD,Single Instruction Single Data stream,单指令流单数据流;
SIMD,Single Instruction Multiple Data stream,单指令流多数据流;
SIMT,Single Instruction Multiple Threads,单指令流多线程;
MISD,Multiple Instruction Single Data stream,多指令流单数据流
MIMD,Multiple Instruction Multiple Data stream,多指令流多数据流。
对于在IM列存储格式中存在的数据,Oracle数据库使用SIMD技术进行处理。
SIMD处理器,就是单条指令能够将数据以单元(矢量)的形式进行处理,而不是一条指令一次只处理一条数据。例如,在进行加法运算时,SISD需要先取得第一个操作数,然后再访问内存,取第二个操作数,然后才能进行求和运算。而对于SIMD而言,它可以一次将运行加法运算的多个数字都加载到矢量中,然后只执行一次加法运算即可。因此SIMD处理有时候被称之为矢量化。
IM列存储最大程度地增加了CPU可以加载到矢量寄存器中并进行评估的列值的数量。数据库不是一次评估一个列中的一个值,而是在一条CPU指令中评估一组列的值。SIMD矢量处理,使得数据库每秒钟可以扫描数十亿行数据。
例如,应用程序发出查询,想在sales表中查找使用promo_id=9999的订单总数。sales表位于IM列存储当中。因此查询从扫描sales.promo_id开始,如下图所示:
CPU将会按照如下方式来对数据进行评估:
1,从promo_id中将前8个值(具体为多少个值,因数据类型和压缩模式而异)加载到SIMD寄存器当中,然后在一条指令中将其与9999进行对比。
2,丢弃对比完的值。
3,再将另外8个值加载到SIMD寄存器当中,继续进行比较。直到将所有值评估完为止。
矢量化联接
In-Memory中的矢量化联接特性,是深度矢量化框架的关键。通过使用SIMD矢量化处理,深度矢量化框架优化了hash join的各个方面,例如hash运算、构建、探测,以及收集等。这一优化技术,能够将hash join的处理性能提高一倍甚至更多。
In-Memory中的矢量化联接特性对用户透明,无需更改执行计划。
In-Memory深度矢量化工作原理
将诸如hash join之类的高级、复杂的SQL运算符,解构为较小的内核大小的单元,然后使用SIMD矢量化技术。数据库以流水线的方式执行操作,从而加速整体进度。
In-Memory矢量化联接的工作方式
1,在运行时,数据库将会自行决定hash join能否从In-Memory深度矢量化技术中受益。如果是,则进入下一步。
注:矢量化联接操作是在运行时发生,因此执行计划中不会予以显示。
2,数据库将连接操作下推给扫描运算符,从而直接在In-Memory的列格式数据上进行评估。
3,该操作将会使用基于SIMD技术优化后的hash表结构,而非传统的hash表。
4,数据库从联接的左侧和右侧来确定匹配的行,并使用矢量化技术将其发回给父级别的SQL运算符。
In-Memory矢量化联接可能会用到的In-Memory特性
联接组
如果声明了联接组,则使用深度矢量化的联接处理,可能会更快。
IM动态扫描
使用轻量级线程在扫描运算符中对联接处理进行并行化。
聚合操作下推
联接顶部的聚合操作,通过联接操作进行矢量化处理。
In-Memory中的列压缩格式
矢量化联接特性极大地利用了列式数据格式。
注:关于联接组,可以参考:https://docs.oracle.com/en/database/oracle/oracle-database/21/inmem/optimizing-queries-with-join-groups.html#GUID-C3ECD34A-965C-4066-9AEC-0F19A775644F;
关于IM动态扫描,可以参考:https://docs.oracle.com/en/database/oracle/oracle-database/21/inmem/in-memory-column-store-architecture.html#GUID-68EA52F3-D62F-474D-99FB-729A6AE43D70;
关于聚合操作下推,可以参考:https://docs.oracle.com/en/database/oracle/oracle-database/21/inmem/optimizing-in-memory-aggregation.html#GUID-2C4FA6C6-3DA8-4CEA-9EF0-294396D15077。
深度矢量化用户接口
当初始化参数INMEMORY_DEEP_VECTORIZATION为true时,则会启用深度矢量化框架。
您可以使用SQL Monitor来确定查询是否使用了矢量化联接。在SQL Monitor报告中,如果DeepVec Hash Joins为1,则表明使用了深度矢量化技术。
示例
我们这里使用customers和orders表,INMEMORY_DEEP_VECTORIZATION设置为false。我们打算计算单个国家/地区的订单数量,并使用深度矢量化技术。
1,登录数据库。
2,使用ALTER SESSION语句将INMEMORY_DEEP_VECTORIZATION设置为true。
3,执行如下SQL:
SELECT /*+monitor */ COUNT(*)
FROM tpch.customer c, tpch.orders o
WHERE c.c_custkey = o.o_custkey
AND c.c_nationkey = 21
4,将上述SQL的SQL ID传递给DBMS_SQL_MONITOR.REPORT_SQL_MONITOR以生成SQL Monitor报告。
5,在浏览器中打开报告。
6,在Details部分查看hash join的详细内容。
7,在其他信息窗口中,可以看到如下结果:
注:这里的DeepVec Hash Join Flags为内部统计指标,用于显示深度矢量化技术采用了哪些优化。