Быстрый старт векторизованного выполнения

1 Перед началом

Перед использованием векторизованного движка выполнения убедитесь, что ваша аппаратная и программная среда соответствуют следующим требованиям:

Аппаратное/программное обеспечение Требование
CPU Процессор Intel с архитектурой Haswell или более новой
YMatrix Развернутая кластерная среда

2 Включение векторизованного выполнения

Векторизованное выполнение включено по умолчанию в YMatrix.

3 Примеры векторизованного выполнения

Сначала создайте таблицу с столбцовым хранением. Ниже приведён пример создания таблицы MARS2:

CREATE TABLE test(
  tag int, 
  i4 int4, 
  i8 int8, 
  f4 float4, 
  f8 float8
  ) USING mars2;
CREATE INDEX ON test USING mars2_btree(tag);

3.1 Оценка выражений

Векторизованный движок выполнения поддерживает распространённые выражения. Например:

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

Это даёт следующий результат:


                                                         QUERY PLAN                                                         
----------------------------------------------------------------------------------------------------------------------------
 Gather Motion 1:1  (slice1; segments: 1)
   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 и алгоритмы, оптимизированные для кэша, для эффективной обработки различных выражений.

3.2 Оптимизация фильтрации WHERE

Для запросов фильтрации в таблицах с столбцовым хранением с условиями WHERE векторизованный движок выполнения обеспечивает ускорение на порядок.

Как показано в плане ниже, MxVScan также поддерживает векторизованную фильтрацию:

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

Результат:

                     QUERY PLAN                     
----------------------------------------------------
 Gather Motion 1:1  (slice1; segments: 1)
   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                    
--------------------------------------------------
 Gather Motion 1:1  (slice1; segments: 1)
   Output: tag, i4, i8, f4, f8
   Merge Key: i8
   ->  Custom Scan (MxVSort) on public.test
         Output: tag, i4, i8, f4, f8
         Sort Key: i8
         ->  Custom Scan (MxVScan) on public.test
               Output: tag, i4, i8, f4, f8
 Optimizer: Postgres query optimizer
(9 rows)

Ещё один пример с ORDER BY и LIMIT:

EXPLAIN (costs off, verbose) SELECT * FROM test ORDER BY i4, i8 DESC LIMIT 10;

Результат:

                          QUERY PLAN                          
--------------------------------------------------------------
 Limit
   Output: tag, i4, i8, f4, f8
   ->  Gather Motion 1:1  (slice1; segments: 1)
         Output: tag, i4, i8, f4, f8
         Merge Key: i4, i8
         ->  Limit
               Output: tag, i4, i8, f4, f8
               ->  Custom Scan (MxVSort) on public.test
                     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 Оптимизация агрегационных запросов

Векторизованный движок выполнения поддерживает агрегационные операторы (такие как sum, min, max, count) для распространённых типов данных, включая int2, int4, int8, float4 и float8.

Пример:

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

Результат:

                                          QUERY PLAN                                           
-----------------------------------------------------------------------------------------------
 Finalize Aggregate
   Output: min((tag + 2)), max((i4 + i8)), count(f8)
   ->  Gather Motion 1:1  (slice1; segments: 1)
         Output: (PARTIAL min((tag + 2))), (PARTIAL max((i4 + i8))), (PARTIAL count(f8))
         ->  Custom Scan (MxVAgg)
               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                             
-------------------------------------------------------------------
 Finalize GroupAggregate
   Output: count(tag), sum(f4), i4
   Group Key: test.i4
   ->  Gather Motion 1:1  (slice1; segments: 1)
         Output: i4, (PARTIAL count(tag)), (PARTIAL sum(f4))
         Merge Key: i4
         ->  Custom Scan (MxVAgg)
               Output: i4, (PARTIAL count(tag)), (PARTIAL sum(f4))
               ->  Custom Scan (MxVSort) on public.test
                     Output: i4, tag, f4
                     Sort Key: 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
;