Реляционное моделирование для экстремального масштабирования хранилищ данных Алексей Халяко Program Manager II 1 Темы Базовые понятия архитектуры хранилищ данных Staging/ODS/архивирование и моделирование Моделирование измерений Почему это моделирование предпочтительно и что плохого в 3NF Типы запросов Стратегии секционирования 2 Что реально имеет смысл. В зависимости от того, какого автора вы читали, они называют одну и ту же «сущность» разными именами Staging/ODS/Архив EDW/DW/Hub Витрина данных, Exploration Mart, уровень отчетов И т.д... до умопомрачения Можно остановиться и перестать заниматься ерундой. В наших диаграммах всегда присутствуют два важнейших объекта: Хранилище – данные находятся физически (на дисках) Трансформации – данные переносятся с одного хранилища на другое. Объект «хранилище» характеризуется «моделью» данных 3 Базис архитектуры– ”Staging” Source A Source B Source C Source D ”ODS” Staged Tables Staged Tables ”Staging” Magic Memory Pipeline 4 Staging/ODS/Архив (SODA) Две задачи Хранить данные, пришедшие от источников (хранилище исходных данных) Временно или «почти» временно? Физическое (диск) хранилище промежуточных наборов данных Иногда, несколько уровней хранилища исходных данных Несколько групп разработчиков часто будут называть каждый уровень по- новому, если другое имя уже используется (как пример: если ODS уже используется, то следующий уровень будет зваться Staging) ИТ обычно не терпит идею многих копий данных Однако: ”One Version of the Truth” != одна модель для всех данных Промежуточные результаты: Сервер, как «расширенная» tempdb, которая «переживет» отказ системы. ..Больше сказать нечего – обычные преимущества промежуточного хранилища данных являются само собой разумеющимся для тех, кто строил проекты с огромными трансформациями данных Staging/ODS/Архив = SODA (Silly Org Driven Abyss*) *Безысходность, продиктованная неразумной организацией 5 Еще об данных из исходных хранилищ Данные, поступающие из хранилищ исходных данных могут быть временными или «полу-временными» Полу-временные данные имеют ряд больших преимуществ Решение о детализации данных всегда может быть изменено Источник всегда может «забыть» какие-то данные, но мы о них помним. Можно сымитировать источник исходных данных, если нужно изменить модель хранилища БЕЗ какого-то взаимодействия с самим источником исходных данных Долговременные промежуточные данные из источника защищают пользователей от неопределенностей Давайте говорить о моделировании, которое имеет смысл Договоримся о «старении» данных каждого хранилища исходных данных (но не переусердствовать) 6 Стоимость архитектуры SODA Хранилище может быть дешевым Использовать SATA или ленты для долговременного хранения промежуточных данных Решить как быстро «стареют» данные в источнике Один хорошо понятный и определенный тип доступа (откуда здесь появиться пользователям?) Данные просто распределены между серверами. Нет необходимости в «СуперБазе» Можно вообще ограничиться дешевыми DAS ”Да, но вы не сможете гарантировать эффективный и простой доступ к 3х годичным данным? Да никаких проблем – мы сможем хранить эти данные за Х $$$. И всегда можем их удалить, если Вы вдруг измените решение.” Не попадайте в западню моделирования хранилища по образу и подобию исходного хранилища данных! Минимизируйте усилия- источники могут иметь «удивительную» структуру -. Так пусть ETL разбирается с этим. Не пытайтесь оптимизировать источники – просто используйте типы данных, которые гарантирую «прием» данных без ошибок. Экономьте ресурсы на перезагрузках данных из источников. Так и так придется данные загружать неоднократно. Гибкость в изменении модели и при росте данных. 7 Базисная архитектура – всё для пользователя! Mart M1 ”EDW” Mart M2 M3 ”Inmon” SODA ”Kimball” Mart M1 Mart M2 M3 8 EDW или не EDW? Не попадайте в западню ”Теория Инмона”: Шаг 1: Сделайте планирование EDW проектом всей компании Шаг 2: Декларируйте: ”one version of the truth” = одна база для управления всеми данными! Шаг 3: Оцените неисчисляемые требования к базе данных, которые защитят инвестиции в проект в долговременной перспективе, однако при ожидании компании роста в 100% в следующие 5 лет, затраты на «железо» будут раны нулю. Если тут вдруг включилось рациональное мышление, перейдите к шагу 2 Повторяйте шаги 2-3 до тех пор пока вас не уволят, или же пока вам не придется работать с идиотической, бесполезной, построенной на политическом влиянии и компромиссах модели.... Обычно этот подход продиктован страхом потери данных Напомню: нам не нужно бояться потерять данные SODA хранит копию для ”быстрой перезагрузки” Эта копия также может хранить версию трансформации (откуда и когда она взялась) Если вдруг потребуется дополнить данные, мы перепишем и перезапустим ETL 9 ”Мини EDW” Случаются ситуации, когда бывает полезно иметь физическую копию оговоренных «версий правды» Допустим, некоторые обще используемые Пример: измерения, особенно схожие представления исторических данных «Материализация» этих данных часто характеризуется более эффективностью ETL процессов и хранения данных Витрина данных (*) при любом EDW – может быть использована как «прототип», чтобы понять, какие типы данные являются обще используемыми Также полезно хранить «преднайденные»версии фактов.... * tactical data mart 10 Вместо того, чтобы думать об … начните собирать требования бизнеса EDW Данные должны быть доступны через … секунд Отчеты содержат активности пользователей за последний час В случае, если потребуются предоставить данные официальным органам, данные за последние ..лет должны быть доступны Например, старые данные могут быть доступны на медленном хранилище В случае выхода системы из строя, последние 3 дня должны быть доступны в первую очередь после начала процесса восстановления. Требования могут идти дальше и быть сложнее Основной вывод: определитесь с основными требованию по доступности, устареванию и потере данных. 11 Что такое latency (задержка)? t0 t1 t2 t3 t4 Mart M1 T(data visible to end user)= Dt1 +Dt2 +Dt3 +Dt4 ”EDW” Mart M2 ”Inmon” M3 SODA t0 t1 t2 Mart M1 ”Kimball” T(data visible to end user)= Dt1 +Dt2 Mart M2 M3 12 Бизнес запросы Определить запросы, которые пользователи выполняют ежедневно. Обычно: Отчет: Поведение подписчика за период времени (billing за прос по определенному сервису) Отчет: Тип поведения подписчика ( уточняющий запрос) Отчет: Поведение всех подписчиков за период времени ( подготовка данных для витрины) Отчет: все пользователи с определенным поведением ( фильтруем всех звонивших в другие сети) Отчет: все звонившие в определенной области/ switch 13 Стратегия секционирования логическая Три возможности Функциональное секционирование – секционирование по subject area Пример: разделить Call Detail Records и Customer Invoices Секционирование по дате – интервал времени. Пример: Разбить по годам 2010, 2009, 2008 Секционирование по ключу/пользователю – по какому-то признаку, который используется для «фильтрации» Пример: секционирование по коду региона или коду пользователя Эти критерии также являются и требованиями бизнеса 14 Секционирование Главная проблема: местонахождение данных Используются вместе = хранятся вместе Сетевой трафик очень дорого стоит Логическое секционирование должно аккуратно соотноситься с физическим Избегайте «нереально-идеальных» архитектур c = 300K km/s - это ограничение не оптимизировать Примеры: Задержка по I/O операциям: 1-5ms (в лучшем случае) Сетевая задержка : 1ms Доступ к памяти: 300ns 15 Секционирование в SQL Варианты: Секционирование таблиц на разных серверах (DPV) Секционирование по нескольким таблицам (PV) Секционирование таблицы (Partition schema/function) Что нужно учитывать: Кластеризация и индексирование для повышения скорости отклика Аггрегирование Загрузка данных Управляемость / Backup Хранилище/архивное хранилище 16 Внутри сервера Local Partitioned View Table Partitioning За: За: Online ”switching” Меньше объектов в базе ”Online” Index Rebuild Больше секций (1000/15 Меньше статистика Против: 000) Против: Поддержка представлений(views) Невозможен online switch (SCH-M locks) Необходимо следить за constraints Перестроение индекса Ограниченное количество секций online только по всей таблице Mix: и то и другое Статистика только на всю таблицу (Фильтрованная статистика может помочь) 17 Секционирование по дате Секционирование по дате, сценарий «скользящее окно» 2010-01-06 00:00 Staging table Staging table 18 Пример применения: Telco сценарий Телекоммуникационные компании Загрузка ~1 TB данных в день Загружать необходимо параллельно: ограниченное окно загрузки и требования по доступности данных Обновлять данные в аналитических системах 4 раза в день «Архивные данные» доступны 3-5 лет. Большая часть данных используется отчетными и аналитическими системами Большие и долго выполняемые SELECT Некоторые ad-hoc запросы к «сегодняшним» данным Fraud detection запросы 19 Движение данных 20 Секционирование для доступности INSERT / UPDATE 2010-08 MSCFact (View) 2010-01 to 2010-07 ALTER VIEW + SWITCH 2009 2008 2007 21 Создание двух уровневого секционирования CSV Area Code: 150 CSV Area Code: 151 CSV Area Code: 152 CSV Area Code: 153 SELECT ... FROM FactCDR WHERE PhoneNumber = 425314159265 AND ChargingDateTime = 20090125 CREATE CLUSTERED INDEX CIX_Date ON MSCFY2009(ChargingDateTime, CarrierCode,PhoneNumber) 22 Example: Multi Level Partitoning FactMSC (view) ALTER TABLE dbo.MSCFY2009 ADD CONSTRAINT CK_DATE CHECK ( [ChargingDateTime] >= '2009-01-01' and [ChargingDateTime] <'2010-01-01') Area Code: 150 Area Code: 150 Area Code: 151 Area Code: 151 Area Code: 152 Area Code: 152 Area Code: 153 Area Code: 153 ALTER TABLE dbo.MSCFY2010 ADD CONSTRAINT CK_DATE_2010 CHECK ( [ChargingDateTime] >='2010-01-01‘ and [ChargingDateTime] <'2011-01-01') GO CREATE CLUSTERED INDEX CIX_Customer ON MSCFY2009(SCarrierCode, PhoneNumber) 23 Как тратится время при загрузке данных? Time Data Extract Dimension Load Fact Key Lookup and compression Data Mart Aggregation 24 Что есть ”хороший ключ”? Характеристики Обоснование Маленький Потому что тогда можно больше ключей загрузить в память и потратить на это меньше IO Это integer Потому что CPUs работает существенно быстрее с integer и это вряд ли изменится в будущем Единожды определив запись, не будет меняться уже никогда Потому что нам нужно в случае изменения записи избежать массивных изменений спровоцированных изменениями других записей, зависимых от изменяемой (аргумент против нормализации) Никогда не используется повторно Потому что мы не хотим, чтобы новые записи неким магическим образом унаследовали данные, которые мы вроде бы как удалили. Результат: достаточно большой спектр значений, чтобы избегать повторений Все, что описано вверху.. Ключ должен быть «тупым» – он не должен знать ничего о записи, к которой он привязан Потому что даже если значение в записи изменяется, ключ должен остаться прежним и ссылаться на те записи, на которые он ссылался. (исключение: время не меняется никогда!) Пользователи НЕ ДОЛЖНЫ помнить этот ключ Мы можем разрешить пользователю знать, что ключ существует, однако никогда не давать возможность оперировать ключом напрямую. Смысл ключа – объединения, выполняемые пользователями. Запрашивается – машинами. 25 Проблема хранилища исходных данных Нужные хорошие ключи, особенно если количество данных растет Хранилища исходных данных такие ключи не смогут предоставить никогда Потому что эти ключи обычно созданы программистами, а не специалистами по моделированию данных Потому что иногда наличие запоминающегося ключа может быть полезна хранилищу исходных данных Мы могли бы довериться источнику в предоставлении хороших данных Однако, это аналогично тому, что верить в то, что источник предоставляет «чистые» данные ... А это, как известно, не происходит никогда. Не верьте, что источник предоставит хорошие ключи. Серьёзно – НИКОГДА! 26 Проблема суррогатных ключей Суррогатные ключи созданы для двух случаев: 1. Используются как компактные integer ключи 2. Выступают в роли ”history trackers” А так как мы всегда можем изменить решение, как мы отслеживаем историю, то суррогатные ключи нам не подходят Наблюдение: имеет смысл только, когда мы показываем SCD второго типа конечным пользователям 27 От источника к пользователю Предположения: Источник никогда не предоставит «хороший ключ» Пользователю нужна модель с измерениями или нечто, что позволит отслеживать историю. На нужно: Связать ключ источника данных с «хорошим ключом» Имеет смысл хранить только «хорошие ключи» Связать «хороший ключ» с суррогатным ( который не «хороший») Не тратить много времени на поиске по ключу. 28 Жизнь таблицы фактов Product History ID_Product SK_Product Product Stage.Order Lines Order Lines Copy Column Type ProductKey CHAR(10) Amount DECIMAL(10,2) OrderKey INT Price DECIMAL(15,2) Stage.Order Headers Order Headers Copy Column Type CustomerKey CHAR(10) OrderKey INT Date DATETIME Internal_ID VARCHAR(20) ID_Product Sales Lookup + Join + Project Mart Reload Lookup Column Type ID_Product INT ID_Customer INT ID_Date INT Sale MONEY + Agg Column Type SK_Product INT SK_Customer INT SK_Date INT Sale MONEY Customer ID_Customer Customer History ID_Customer SK_Customer Source SODA ”EDW” Data Mart 29 Как отслеживать/изменять историю Ключ может измениться Stage.Order Lines Column Type ProductKey CHAR(10) Amount DECIMAL(10,2) OrderKey Price Stage.Order Headers Column Type CustomerKey CHAR(10) OrderKey INT Date DATETIME Internal_ID VARCHAR(20) SODA Type ID_Product INT ProductKey CHAR(10) Sales Column Column INT DECIMAL(15,2) Column Lookup + Join + Projec Type Type ProductKey ID_Product CHAR(10) INT Amount ID_Customer OrderKey DECIMAL(10,2) INT INT Price ID_Date DECIMAL(15,2) INT CustomerKey Sale Date CHAR(10) MONEY DATETIME Internal_ID Column Type ID_Product INT ProductKey CHAR(10) Prouct Name CHAR(10) Column Type ID_Customer INT CustomerKey CHAR(10) CustomerName CHAR(20) VARCHAR(20) CustomerAddress CHAR(20) Наше представление об истории может измениться. Column Type CustomerKey CHAR(10) ID_Customer INT ”EDW” Date_BEGIN DATE Date_End DATE Data Mart 30 BETWEEN двумя мирами Какой join нужно построить, чтобы получить результат? Product History ID_Product SK_Product Valid_From Valid_To SELECT ... FROM Sales S JOIN Product_History P ON S.ID_Product = P.ID_Product Product AND ID_Date BETWEEN P.Valid_From ID_Product AND Valid_To Sales Как это повлияет на работу оптимизатора? Нет никаких статистик, которые могут помочь оценить эффективно “BETWEEN” Column Type ID_Product INT ID_Customer INT ID_Date INT Sale MONEY Column Type SK_Product INT SK_Customer INT Sale MONEY Вы реально хотите, чтобы пользователи страдали от такой модели? 31 Высокоуровневая архитектура EDW может играть роль промежуточного хранилища ”agreed results” Выполняем сколько угодно операционных задач (чистота данных) Полагаемся на SODA, чтобы «проиграть заново» данные Быстрый ETL «откат» не так сложно организовать! Не полагаться на ключи источника, оптимизировать для оптимальных типов данных Исходя из этого мы предполагаем, что: Все ключи integers Данные никогда не теряются = мы можем моделировать и «выкидывать» данные, которые нам не нужны. Оптимизация для наибольшей скорости доступности данных Данные joined по одному ключу Таблицы ”pre projected” – мы работаем только со столбцами, которые нам нужны 32 Нормализовать или денормализовать? Нормализация Меньший объем хранилища Больше гибкости/управляемость Меньше влияние от изменения модели данных Можно упражняться в Join’ах Проще управлять Проще загружать данные (ой ли?) “Никогда не теряется история” Хранилища в ответе за всё! Де-нормализация Быстрые запросы (JOIN) Не забываем о column store (оптимизированно) Понятно пользователям Меньше вероятность, что оптимизатор засбоит Ожидаемая производительность т.е. Teradata/PDW/Hadoop etc.. 33 “Типичный подход групп IT” Разве это выглядит как плохая модель? Does it look like a bad design? Customer “измерение” Product “измерение” Sales “измерение” SELECT ALL Customers from Geography = 'Country' WHERE PRODUCT = 'Product' and SalesAmount > '$100USD' 34 Магические JOIN! 35 Sizing Storage cache 4GB-512 GB 200K IOPS sec Up to 2 PB Server 8 CPU up to 8 cores each Up to 2TB memory Is this enough to build DW? 36 Sizing Prototype system Identify main system load through the set query types Scan queries balance vs look up queries Use the approach from Fast Track core calculator User Variable Input Anticipated total number of users expected on the system Estimated percent of actual query concurrency Fast Track DW CPU max core consumption rate (MCR) in MB/s of page compressed data per core Estimated compression ratio (default = 2.5:1) Estimated drive serial throughput speed in compressed MB/s Number of data drives in single storage array Usable capacity per drive Space Reserved for TempDB Adjust for workload mix 3.000 us ers Estimated % Estimated % of data found in workload SQL Server cache Estimated Query Desired Query Data Estimated Disk Response Time Scan Volume Scan volume MB (seconds) MB (Uncompressed) (under load) (Uncompressed) 1% concurrency Si mpl e 70% 10% 8.000 25 7.200 200 MB/s Avera ge 20% 0% 75.000 180 75.000 2,5 :1 Compl ex 10% 0% 450.000 1.200 450.000 100% 100 MB/s 8 dri ves 272 GB 26% Calculations and Results % of core consumption rate achieved Simple Average Complex 100% 50% 25% Expected per CPU core consumption rate (MB/s) 200 100 50 Calculated Single Query Scan Volume in MB (compressed) 2.880 30.000 180.000 Calculated Target Concurrent Queries Estimated Target Queries per Hour Required IO Throughput in MB/s Estimated Estimated Single Number of Query Run Time Cores Required (seconds) 21 6 3 3.024 120 9 2.419 1.000 450 12,10 10,00 9,00 30 3.153 3.869 32,00 0,5 9,4 112,5 37