向量化快速上手

1 在开始之前

在开始使用向量化执行引擎之前,你需要率先准备好正确的软硬件环境:

软硬件环境 准备
CPU Intel CPU,Haswell 架构或以上
YMatrix 部署好的集群环境

2 启用向量化

YMatrix 默认开启向量化。

3 向量化使用示例

首先,我们需要一个面向列存的数据表。下面创建一个 MARS3 表。

=# CREATE TABLE test(
   tag int, 
   i4 int4, 
   i8 int8, 
   f4 float4, 
   f8 float8
   ) 
   USING MARS3
   ORDER BY (tag);

3.1 表达式计算

向量化执行引擎支持常见表达式,例如:

=# EXPLAIN (costs off, verbose) SELECT tag + 10, f4 * -1, f8 / 10 + i8 * i4 FROM test;

得到如下输出:

                                                         QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
 Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
   Output: ((tag + 10)), ((f4 * '-1'::double precision)), (((f8 / '10'::double precision) + ((i8 * i4))::double precision))
   ->  Custom Scan (MxVScan) on public.test
         Output: (tag + 10), (f4 * '-1'::double precision), ((f8 / '10'::double precision) + ((i8 * i4))::double precision)
 Optimizer: Postgres query optimizer
(5 rows)

其中 MxVScan 是包含了核心计算模块,利用 SIMD 指令和 CPU 缓存友好的算法,能够高效处理各种表达式。

3.2 WHERE 过滤优化

针对列存表的 WHERE 条件过滤查询,向量化执行引擎也有数量级的优化提升。 如下计划所示,除了计算外,MxVScan 也是具备向量化过滤的功能:

=# EXPLAIN (costs off, verbose) SELECT * FROM test where i4 > 10 and i8 < 8;

得到如下输出:

                            QUERY PLAN
------------------------------------------------------------------
 Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
   Output: tag, i4, i8, f4, f8
   ->  Custom Scan (MxVScan) on public.test
         Output: tag, i4, i8, f4, f8
         Filter: ((test.i4 > 10) AND (test.i8 < 8))
 Optimizer: Postgres query optimizer
(6 rows)

3.3 实现排序查询优化

向量化执行引擎实现了面向列存的排序算法。同时,针对 Limit 算子也有特殊优化。Limit 算子用于限制数据输出的行数。启用向量化后,算子占用内存更少,速度更快。示例如下:

=# EXPLAIN (costs off, verbose) SELECT * FROM test ORDER BY i8;

得到如下输出:

                            QUERY PLAN
------------------------------------------------------------------
 Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
   Output: tag, i4, i8, f4, f8
   Merge Key: i8
   ->  Custom Scan (MxVSort)
         Output: tag, i4, i8, f4, f8
         Sort Key: test.i8
         ->  Custom Scan (MxVScan) on public.test
               Output: tag, i4, i8, f4, f8
 Optimizer: Postgres query optimizer
(9 rows)
=# EXPLAIN (costs off, verbose) SELECT * FROM test ORDER BY i4, i8 DESC LIMIT 10;

得到如下输出:

                               QUERY PLAN
------------------------------------------------------------------------
 Custom Scan (MxVLimit)
   Output: tag, i4, i8, f4, f8
   ->  Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
         Output: tag, i4, i8, f4, f8
         Merge Key: i4, i8
         ->  Custom Scan (MxVLimit)
               Output: tag, i4, i8, f4, f8
               ->  Custom Scan (MxVSort)
                     Output: tag, i4, i8, f4, f8
                     Sort Key: test.i4, test.i8
                     ->  Custom Scan (MxVScan) on public.test
                           Output: tag, i4, i8, f4, f8
 Optimizer: Postgres query optimizer
(13 rows)

3.4 实现聚集查询优化

向量化执行引擎针对常见数据类型(int2, int4, int8, float4, float8 等)实现了各类聚集算子,如 sum, min, max, count 等。

=# EXPLAIN (costs off, verbose) SELECT min(tag + 2), max(i4 + i8), count(f8) FROM test;

得到如下输出:

                                          QUERY PLAN
-----------------------------------------------------------------------------------------------
 Custom Scan (MxVAgg) Finalize Aggregate
   Output: (min((tag + 2))), (max((i4 + i8))), (count(f8))
   ->  Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
         Output: (PARTIAL min((tag + 2))), (PARTIAL max((i4 + i8))), (PARTIAL count(f8))
         ->  Custom Scan (MxVAgg) Partial Aggregate
               Output: (PARTIAL min((tag + 2))), (PARTIAL max((i4 + i8))), (PARTIAL count(f8))
               ->  Custom Scan (MxVScan) on public.test
                     Output: tag, i4, i8, f8
 Optimizer: Postgres query optimizer
(9 rows)
=# EXPLAIN (costs off, verbose) SELECT count(tag), sum(f4) FROM test GROUP BY i4;

得到如下输出:

                                     QUERY PLAN
------------------------------------------------------------------------------------
 Custom Scan (MxVMotion) Gather Motion 4:1  (slice1; segments: 4)
   Output: (count(tag)), (sum(f4)), i4
   ->  Custom Scan (MxVHashAgg) Finalize HashAggregate
         Output: (count(tag)), (sum(f4)), i4
         Group Key: test.i4
         ->  Custom Scan (MxVMotion) Redistribute Motion 4:4  (slice2; segments: 4)
               Output: i4, (PARTIAL count(tag)), (PARTIAL sum(f4))
               Hash Key: i4
               ->  Custom Scan (MxVHashAgg) Partial HashAggregate
                     Output: i4, (PARTIAL count(tag)), (PARTIAL sum(f4))
                     Group Key: test.i4
                     ->  Custom Scan (MxVScan) on public.test
                           Output: i4, tag, f4
 Optimizer: Postgres query optimizer
(14 rows)

3.5 其他复杂查询优化

针对更为复杂的查询,向量化执行引擎也有显著的提升作用。 例如:

=# SELECT SUM(lo_extendedprice * lo_discount) AS revenue
  FROM tname
 WHERE lo_orderdate >= '1993-01-01'
   AND lo_orderdate <  '1994-01-01'
   AND lo_discount between 1 and 3
   AND lo_quantity < 25
;