Быстрый старт
Развертывание
Моделирование данных
Подключение
Запись данных
Миграция
Запросы
Операции и обслуживание
Типовое обслуживание
Секционирование
Резервное копирование и восстановление
Масштабирование
Зеркалирование
Управление ресурсами
Безопасность
Мониторинг
Настройка производительности
Устранение неполадок
Справочник
Руководство по инструментам
Типы данных
Хранилище данных
Выполняющая система
Потоковая передача
Восстановление после сбоев
Конфигурация
Индексы
Расширения
Справочник по SQL
Часто задаваемые вопросы
В этом документе описываются принципы и способы использования техники оптимизации Runtime Filter для повышения производительности запросов.
Runtime Filter — одна из ключевых технологий для повышения производительности движка выполнения YMatrix. Это динамический фильтр, создаваемый во время выполнения запроса после того, как оптимизатор сгенерировал физический план выполнения. Это отличается от фильтров, заранее запланированных оптимизатором.
Соединение (Join) — один из самых сложных операторов в SQL-запросах.
Возьмём в качестве примера Hash Join: движок выполнения сначала сканирует внутреннюю таблицу (обычно меньшую), чтобы построить хеш-таблицу, затем сканирует внешнюю таблицу, вычисляет хеш-значения и сопоставляет строки по условию соединения. Первый этап называется build side, второй — probe side.
Поскольку внешняя таблица обычно содержит множество строк, её сканирование вместе с передачей данных, хешированием и сопоставлением требует значительного времени. Если внешнюю таблицу можно отфильтровать на ранней стадии, производительность запроса может значительно повыситься.
Runtime Filter снижает объём ввода-вывода при сканировании внешней таблицы и этапах shuffle (перераспределении данных между сегментами), применяя фильтры во время выполнения. Это улучшает производительность запросов. Например, при выполнении TPC-H Q17 на YMatrix включение Runtime Filter обеспечивает почти 20-кратное улучшение производительности по сравнению с его отключением.
В YMatrix Runtime Filter включён по умолчанию. Оптимизатор на основе стоимости решает, применять ли Runtime Filter, исходя из оценённой стоимости выполнения.
Примечание!
Чтобы отключить Runtime Filter вручную, установите:set mx_enable_runtime_filter=off;в вашей сессии.
Дополнительные параметры см. в разделе Параметры конфигурации Runtime Filter.
План и детали выполнения Runtime Filter отображаются с помощью EXPLAIN.
Примечание!
Чтобы отобразить информацию о Runtime Filter в выводе EXPLAIN, используйте ключевое словоVERBOSE.
Создайте таблицу rt_ao_t1:
CREATE TABLE rt_ao_t1
(
c1 int,
c2 int
)
WITH (appendoptimized=true, orientation=column, compresslevel=1)
DISTRIBUTED BY(c1);
Создайте таблицу rt_ao_t2:
CREATE TABLE rt_ao_t2
(
c1 int,
c2 int
)
WITH (appendoptimized=true, orientation=column, compresslevel=1)
DISTRIBUTED BY(c1);
План 1
Следующий план показывает два экземпляра ключевого слова RuntimeFilterType — один под узлом Hash и один под узлом MxVScan.
Где:
local указывает, что Runtime Filter является локальным и не проходит через Motion-узел.initiator указывает инициатора Runtime Filter (то есть узел Hash), а target — цель (то есть узел MxVScan).EXPLAIN (VERBOSE) SELECT * FROM rt_ao_t1 t1, rt_ao_t2 t2 WHERE t1.c1 = t2.c1;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=73.47..284.43 rows=10000 width=16)
Output: t1.c1, t1.c2, t2.c1, t2.c2
-> Hash Join (cost=73.47..151.10 rows=3333 width=16)
Output: t1.c1, t1.c2, t2.c1, t2.c2
Hash Cond: (t1.c1 = t2.c1)
-> Custom Scan (MxVScan) on public.rt_ao_t1 t1 (cost=0.00..31.80 rows=3333 width=8)
Output: t1.c1, t1.c2
RuntimeFilterType: local, target
-> Hash (cost=31.80..31.80 rows=3333 width=8)
Output: t2.c1, t2.c2
RuntimeFilterType: local, initiator
-> Custom Scan (MxVScan) on public.rt_ao_t2 t2 (cost=0.00..31.80 rows=3333 width=8)
Output: t2.c1, t2.c2
Optimizer: Postgres query optimizer
Settings: enable_hashjoin=on, enable_mergejoin=off, enable_nestloop=off, mx_enable_runtime_filter=on, mx_interconnect_compress=on, mx_runtime_join_ratio=0, mx_runtime_min_outer_rows=0
(15 rows)
План 2
Этот план отличается от предыдущего тем, что Hash Join требует Motion-узла. Поэтому тип Runtime Filter — global. Кроме того, Motion-узел помечен как broker, что означает, что Runtime Filter должен передаваться через этот узел.
EXPLAIN (VERBOSE) SELECT * FROM rt_ao_t1 t1, rt_ao_t2 t2 WHERE t1.c2 = t2.c2;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=140.13..417.77 rows=10000 width=16)
Output: t1.c1, t1.c2, t2.c1, t2.c2
-> Hash Join (cost=140.13..284.43 rows=3333 width=16)
Output: t1.c1, t1.c2, t2.c1, t2.c2
Hash Cond: (t1.c2 = t2.c2)
-> Custom Scan (MxVMotion) Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..98.47 rows=3333 width=8)
Output: t1.c1, t1.c2
Hash Key: t1.c2
RuntimeFilterType: global, broker
-> Custom Scan (MxVScan) on public.rt_ao_t1 t1 (cost=0.00..31.80 rows=3333 width=8)
Output: t1.c1, t1.c2
RuntimeFilterType: global, target
-> Hash (cost=98.47..98.47 rows=3333 width=8)
Output: t2.c1, t2.c2
RuntimeFilterType: global, initiator
-> Custom Scan (MxVMotion) Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..98.47 rows=3333 width=8)
Output: t2.c1, t2.c2
Hash Key: t2.c2
-> Custom Scan (MxVScan) on public.rt_ao_t2 t2 (cost=0.00..31.80 rows=3333 width=8)
Output: t2.c1, t2.c2
Optimizer: Postgres query optimizer
Settings: enable_hashjoin=on, enable_mergejoin=off, enable_nestloop=off, mx_enable_runtime_filter=on, mx_interconnect_compress=on, mx_runtime_join_ratio=0, mx_runtime_min_outer_rows=0
(21 rows)
Чтобы получить детали выполнения Runtime Filter, используйте EXPLAIN ANALYZE.
Вывод включает:
c1)EXPLAIN ANALYZE SELECT * FROM rt_ao_t1 t1, rt_ao_t2 t2 WHERE t1.c1 = t2.c1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=73.47..284.43 rows=10000 width=16) (actual time=11.124..15.917 rows=10000 loops=1)
-> Hash Join (cost=73.47..151.10 rows=3333 width=16) (actual time=8.923..13.268 rows=3385 loops=1)
Hash Cond: (t1.c1 = t2.c1)
-> Custom Scan (MxVScan) on rt_ao_t1 t1 (cost=0.00..31.80 rows=3333 width=8) (actual time=1.709..3.520 rows=3385 loops=1)
RuntimeFilter: BloomFilter, column:c1, keys:3385, mem(KB):128, inputrows:3385, outputrows:3385, batch:53
-> Hash (cost=31.80..31.80 rows=3333 width=8) (actual time=4.813..4.813 rows=3385 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 4229kB
-> Custom Scan (MxVScan) on rt_ao_t2 t2 (cost=0.00..31.80 rows=3333 width=8) (actual time=1.933..2.777 rows=3385 loops=1)
Planning Time: 3.398 ms
(slice0) Executor memory: 94K bytes.
(slice1) Executor memory: 9367K bytes avg x 3 workers, 9379K bytes max (seg1). Work_mem: 4229K bytes max.
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 17.945 ms
(14 rows)
Runtime Filter — это оптимизация для Hash Join. Следовательно, любой запрос, использующий Hash Join, может попытаться применить Runtime Filter. Однако окончательное решение зависит от оценок стоимости, выполняемых оптимизатором на этапах планирования и выполнения.
Runtime Filter оценивается как на этапе планирования, так и на этапе выполнения. На этапе планирования, если размеры внутренней и внешней таблиц не соответствуют определённым критериям, фильтр не создаётся. На этапе выполнения, если фактический объём данных существенно отличается от оценок, Runtime Filter может быть отменён.
Используйте EXPLAIN VERBOSE, чтобы просмотреть план запроса. Если план содержит ключевое слово Runtime Filter, Runtime Filter будет использован при выполнении.