
Привет, Хабр!
На связи Артемий Козырь из команды Аналитики, и я продолжаю знакомить вас с Wheely. В этом выпуске:
- Основы гибких кластерных вычислений
- Колоночное хранение и компрессия данных
- Вместо индексов: ключи сегментации и сортировки
- Управление доступами, правами, ресурсами
- Интеграция с S3 или Даталейк на ровном месте
Все аналитические решения Wheely так или иначе строятся на основе Хранилища Данных, движком которого выступает продукт с кодовым названием Redshift от провайдера облачных сервисов Amazon. Но почему именно этот продукт?
Эту публикацию я бы охарактеризовал как базовую и основополагающую. Сложные механизмы и принципы работы системы скрыты от бизнес-пользователей, но именно они лежат в основе производительного и современного решения. Постараюсь внести ясность и подчеркнуть для вас ключевые особенности.
Кластерные вычисления как основа архитектуры
Кластер состоит из leader node (координатор) и набора compute node (вычислительный узел). Координатор играет роль связующего звена между кластером и пользовательскими приложениями, генерирует планы запросов, управляет коммуникацией. Вычислительные узлы — рабочие лошадки, на которых выполняется основная часть расчетов.
Redshift обеспечивает параллельную обработку данных на кластере машин
Этот принцип широко известен как MPP (massively parallel processing, массово-параллельная архитектура). Не лишним будет упомянуть и другие популярные СУБД, использующие подобные принципы: BigQuery, Vertica, Greenplum, Teradata, Azure SQL DW.
Каждая compute node обладает набором выделенных ресурсов: CPU, memory, disk, которые определяются типом виртуальной машины.
Спецификация типов compute node доступных для Amazon Redshift
Сегодня в Wheely мы используем 8 узлов типа dc2.large, что в сумме составляет 16 vCPU, 120 GiB памяти, 1.3 TB объем диска. Кто-то может справедливо заметить, что это не такие уж и огромные объемы данных, на что я бы возразил: суть не в объеме, а в том, какие результаты и пользу вы можете выжать из этих данных.
Не могут не радовать элементы гибкости и эластичности (elasticity), в целом присущие облачным сервисам. С ростом бизнеса и потребности в аналитике несколько раз без особого труда производилось расширение кластера: увеличивалось количество узлов (resize), осуществлялся переход на новое поколение виртуальных машин (node upgrade).
Concurrency Scaling позволит поднять временный кластер для того чтобы справиться с пиковой нагрузкой
В моменты пиковых нагрузок производительность на стабильном уровне может поддержать функция concurrency scaling, которая автоматически добавляет вычислительные мощности в виде временных compute nodes, которые "гасятся" после спада нагрузки.
Колоночное хранение и компрессия данных
В противовес классическим операционным СУБД (PostgreSQL, MySQL, SQL Server), хранящим данные в строковом формате (row-oriented storage), Redshift использует все преимущества колоночного хранения (column-oriented storage). Блоки на диске заполняются данными одной колонки, и каждая колонка хранится отдельно от любой другой.
Это дает несколько неоспоримых преимуществ для аналитических нагрузок. Прежде всего для операций проекции (запросе каких-то конкретных колонок). Представьте себе широкую таблицу фактов из 100+ колонок; для формирования результата запроса нам из них понадобятся только 5. При колоночном хранении мы с диска прочтем ровно 5 запрашиваемых колонок. При строковом хранении пришлось бы читать все 100+ колонок и потом отбросить бОльшую часть, что в разы увеличивает интенсивность I/O и нагрузку на диск.
Колоночное хранение организовывает в блоки данные одной колонки (не строки!)
Во-вторых, будучи однородными, данные одной колонки весьма успешно поддаются сжатию (compression). Объясняя на пальцах, нет необходимости хранить наименование тарифа (Business, First, Luxe) для каждой поездки. Достаточно сделать одну запись и указать, на какое количество строк будет распространяться это значение: {100, Luxe}. Эффект становится особенно заметен, когда количество строк исчисляется сотнями тысяч и миллионами. На деле всё несколько сложнее: кодеков (алгоритмов) сжатия около десятка, и у каждого есть свои особенности и лучшие сценарии для применения.
Пример сжатия данных алгоритмом Runlength encoding
Однако при должном усердии можно добиться еще более значительного сжатия, чем дефолтные кодеки, выбранные Amazon Redshift. Чуть подробнее этот вопрос я раскрывал в публикации Compressing Redshift columnar data even further with proper encodings.
Пересмотр алгоритмов сжатия данных позволил сэкономить 21% дискового пространства
Ключи сегментации и сортировки вместо индексов
В Redshift вторичные поисковые структуры данных (индексы) в привычном понимании (B-Tree, Bitmap) отсутствуют. Здесь они просто не нужны, и вот почему:
Тонкая настройка позволяет задать принцип, по которому строки будут распределены между узлами кластера: равномерное (EVEN), копия на каждом (ALL), или по ключу (KEY). Эта конфигурация носит название тип сегментации (distribution style).
3 типа распределения каждой строки данных в кластере: KEY, ALL, EVEN
А уже данные в блоках на каждом узле можно физически хранить в заданном порядке, то есть отсортированными. На ум приходит сортировка, например, по монотонно возрастающему идентификатору. Конфигурация, использующая один и тот же атрибут в distribution key, sort key обеспечит использование самого оптимального типа соединения таблиц — SORT MERGE JOIN:
{{ config( dist='request_id', sort='request_id' ) }}
Смотрите на это как на конструкцию ORDER BY в SQL-запросе, сохраняющую порядок в таблице на диске. При этом задействованы могут быть несколько колонок — тогда это уже составной ключ (compound sort key).
{{ config( materialized='table', dist="city", sort=['city', 'date', 'product_name'] ) }}
В дополнение, есть еще такой очень хитрый вид сортировки как Interleaved sort key, который дает одинаковый вес любой из колонок (или их комбинации) в ключе сортировки. Он отлично подходит к витринам данных, для которых нет одного заранее известного паттерна доступа.
{{ config( materialized='table', dist="journey_id", sort_type='interleaved', sort=["completed_ts_loc" , "city" , "country" , "service_group" , "is_airport" , "is_wheely_journey"] ) }}
Вкупе с колоночным хранением данных это дает поразительные результаты с точки зрения производительности и использования ресурсов.
Разграничение прав доступа и ресурсных квот
На мой взгляд, это один из фундаментальных вопросов, напрямую влияющий на безопасностью и работоспособность кластера:
- любой пользователь принадлежит к группе с четким скоупом прав
- все запросы разбиваются на категории и обрабатываются с различным приоритетом
Структура лучше хаоса. Концептуально можно сделать так:
- Бизнес-пользователи смотрят только на витрины данных
- Аналитики видят стейдж и промежуточные таблицы
- Инженеры видят сырые данные и метаданные
- Админ видит их всех 🙂
Amazon Redshift является форком широко известной PostgreSQL и поэтому синтаксис многим покажется знакомым:
---------------------- -- USER MANAGEMENT --- ---------------------- CREATE USER etl WITH PASSWORD '' ; CREATE USER hevo WITH PASSWORD '' ; CREATE USER dbt WITH PASSWORD '' ; CREATE USER da WITH PASSWORD '' ; CREATE USER nb WITH PASSWORD '' ; CREATE USER looker WITH PASSWORD '' SYSLOG ACCESS UNRESTRICTED ; CREATE USER ar WITH PASSWORD '' ; CREATE USER ak WITH PASSWORD '' ; ------------------------- --- SCHEMA MANAGEMENT --- ------------------------- CREATE SCHEMA IF NOT EXISTS hevo AUTHORIZATION hevo ; CREATE SCHEMA IF NOT EXISTS ext AUTHORIZATION etl ; CREATE SCHEMA IF NOT EXISTS flatten AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS staging AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS intermediate AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS analytics AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS ad_hoc AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS meta AUTHORIZATION dbt ; CREATE SCHEMA IF NOT EXISTS looker_scratch AUTHORIZATION looker ; ----------------------- -- GROUP MANAGEMENT --- ----------------------- CREATE GROUP etl WITH USER etl, hevo ; CREATE GROUP dbt WITH USER dbt ; CREATE GROUP analytics WITH USER da, nb ; CREATE GROUP bi WITH USER looker ; CREATE GROUP business_users WITH USER ar, ak ; ---------------------------- -- PRIVILEGES MANAGEMENT --- ---------------------------- -- GROUP etl GRANT USAGE ON SCHEMA hevo, staging, flatten, analytics, intermediate TO GROUP etl ; -- GROUP dbt GRANT USAGE ON SCHEMA hevo, snapshots TO GROUP dbt ; GRANT USAGE, CREATE ON SCHEMA ext TO GROUP dbt ; GRANT SELECT ON ALL tables IN SCHEMA hevo TO GROUP dbt ; GRANT ALL PRIVILEGES ON ALL tables IN SCHEMA meta, ext, snapshots TO GROUP dbt ; ALTER DEFAULT PRIVILEGES FOR USER hevo IN SCHEMA hevo GRANT SELECT ON tables TO GROUP dbt ; ALTER DEFAULT PRIVILEGES FOR USER etl IN SCHEMA ext GRANT ALL PRIVILEGES ON tables TO GROUP dbt ; -- GROUP analytics GRANT USAGE ON SCHEMA hevo, ext, flatten, staging, intermediate, restricted, analytics, meta TO GROUP analytics ; GRANT USAGE, CREATE ON SCHEMA ad_hoc TO GROUP analytics ; GRANT SELECT ON ALL tables IN SCHEMA hevo, ext, flatten, staging, intermediate, restricted, analytics, meta TO GROUP analytics ; GRANT ALL PRIVILEGES ON ALL tables IN SCHEMA ad_hoc TO GROUP analytics ; ALTER DEFAULT PRIVILEGES FOR USER dbt IN SCHEMA flatten, staging, intermediate, restricted, analytics, meta GRANT SELECT ON tables TO GROUP analytics ; ALTER DEFAULT PRIVILEGES FOR USER dbt IN SCHEMA ad_hoc GRANT ALL PRIVILEGES ON tables TO GROUP analytics ; -- GROUP bi GRANT USAGE ON SCHEMA analytics, meta, ad_hoc, snapshots TO GROUP bi ; GRANT SELECT ON ALL tables IN SCHEMA analytics, meta, ad_hoc TO GROUP bi ; ALTER DEFAULT PRIVILEGES FOR USER dbt IN SCHEMA analytics, meta, ad_hoc GRANT SELECT ON tables TO GROUP bi ; -- GROUP business users GRANT USAGE ON SCHEMA analytics TO GROUP business_users ; GRANT USAGE, CREATE ON SCHEMA ad_hoc TO GROUP business_users ; GRANT SELECT ON ALL tables IN SCHEMA analytics TO GROUP business_users ; GRANT ALL PRIVILEGES ON ALL tables IN SCHEMA ad_hoc TO GROUP business_users ; ALTER DEFAULT PRIVILEGES FOR USER dbt IN SCHEMA analytics GRANT SELECT ON tables TO GROUP business_users ;
У Amazon Redshift очень неплохие настройки automatic workload management (WLM), т.е. автоматическое управление параллелизмом запросов и выделением ресурсов. Но на каком-то моменте и его усилия достигают предела. Redshift просто не может знать всё о специфике вашей нагрузки:
- Периодичность и время запуска ELT
- Приоритетные часы для BI и Ad-hoc
- Какие запросы можно “отстреливать” и почему
- Наиболее важные запросы, которые точно должны завершаться
Конфигурация очередей (WLM) позволяет гибко управлять нагрузкой на кластер
Однако это уже тема отдельной публикации, и потенциально я могу сделать подробный доклад по разграничению прав доступа и тонкой настройки очередей.
Отдельно хочется упомянуть про short-query acceleration. Amazon Redshift гордится использованием ML-алгоритмов для предсказания времени выполнения запросов, и короткие (~ до 30 сек.) пропускает впереди тех, что будут выполняться долго. В любом случае, после включении этой фичи у кластера Wheely как будто открылось второе дыхание, а BI здорово ускорился.
Data Lake ближе чем вы можете представить
Что там с возможностью устроить Даталейк на ровном месте? Она есть! Вместе с расширением Redshift Spectrum кластер приобретает новые возможности:
- В виде SQL DDL описывать внешние источники данных (файлы в S3)
- Выполнять запросы к таким данным: доступны проекции (SELECT), фильтры (WHERE), соединения наборов данных (JOINs), вставка (INSERT)
- Работать с вложенными и полу-структурированными данными: JSON, ORC, PARQUET
Всё это напоминает широко известные EXTERNAL TABLE в _Hive. _И по сути так оно и есть: под капотом используется именно Hive Metastore.
Благодаря Spectrum в Redshift доступен широкий набор популярных форматов данных
В Wheely мы нашли несколько применений Spectrum:
1. Data Quality Pipeline
Каждый день при помощи S3 и Spectrum выполняется кросс-сверка операционной базы данных (MongoDB) и Хранилища (Redshift). Чуть подробнее я описывал это в публикации Кто ответит за качество аналитики: QA для Хранилища Данных, и с тех пор даже есть значительные усовершенствования.
2. Архивирование холодных данных в S3
Холодные данные сроком давности >3 лет мы выгружаем в S3 в бинарный колоночный формат parquet. Данные всё так же доступны для запросов пользователей, однако дорогостоящее место в кластере Redshift они уже не занимают, что замечательно.
UNLOAD ('SELECT * FROM "hevo"."events_prod_clickstream_archive"') TO 's3://wheely_analytics/dwh/hevo/events_prod/clickstream_archive' IAM_ROLE '' MANIFEST FORMAT AS PARQUET NULL AS '' MAXFILESIZE AS 256 ENCRYPTED AUTO ;
В планах у меня еще одна грандиозная идея: хочется создать полноценный дата-лейк. Но об этом позже.
В случае факапа восстановитесь из бэкапа
Вместо тысячи слов
Обычно я не вставляю мемы в публикации, но тут не смог удержаться. Случайно наткнулся и нашел его очень смешным и жизненным. Ситуация может произойти с каждым, и я не исключение. Благо случай не был связан с витринами и production-таблицами, а произошел в рамках одной ad-hoc задачи.
Суть в том, что с недавнего времени появилась возможность восстановить единичные таблицы из бэкапа в указанное целевое место назначения (target table). Очень легко восстановить удаленную или испорченную таблицу из бэкапа за определенную дату. И именно таблицу, а не снапшот целиком. И это не может не радовать. Несколько раз пользовались, и, надеюсь, хватит.
Восстановить удаленную или испорченную таблицу из бэкапа теперь как никогда просто и быстро
Ну и, конечно же, стоит упомянуть что бэкапы выполняются автоматически с периодичностью в несколько часов и горизонтом в 7 суток.
Очень ждём: in-database ML, native semi-structured data support
Даже несмотря на все перечисленные достоинства всегда есть куда развиваться. И команде Wheely как искушенным пользователям всегда хочется большего.
Облизываясь, я смотрю на новые фичи Amazon Redshift, которые уже находятся в статусе preview (пока доступны для тестовых кластеров):
- Using machine learning in Amazon Redshift
- Ingesting and querying semistructured data in Amazon Redshift
Кажется, я уже придумал им достойное применение. Очень ждём! И, конечно, подготовим свежие обзоры и доклады.
Интересно? Присоединяйся к команде Wheely. Или свяжись со мной и задай вопросы — буду рад ответить.
Следить за моими публикациями в авторском канале: https://t.me/enthusiastech.
Благодарю за внимание.
ссылка на оригинал статьи https://habr.com/ru/company/wheely/blog/539154/











Добавить комментарий