<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Аналитик на минималках</title><generator>teletype.in</generator><description><![CDATA[База знаний телеграмм канала &quot;Аналитик на минималках&quot;.
Про аналитику, IT, карьеру, нейросети, программирование.]]></description><image><url>https://img4.teletype.in/files/7e/a1/7ea16cea-7040-4ef6-a8ae-6d55f1010b68.png</url><title>Аналитик на минималках</title><link>https://notes.darin.pro/</link></image><link>https://notes.darin.pro/?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=darin.pro</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/darin.pro?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/darin.pro?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Wed, 06 May 2026 10:59:24 GMT</pubDate><lastBuildDate>Wed, 06 May 2026 10:59:24 GMT</lastBuildDate><item><guid isPermaLink="true">https://notes.darin.pro/dwh</guid><link>https://notes.darin.pro/dwh?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=darin.pro</link><comments>https://notes.darin.pro/dwh?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=darin.pro#comments</comments><dc:creator>darin.pro</dc:creator><title>Паттерны проектирования КХД</title><pubDate>Thu, 31 Jul 2025 17:06:26 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/56/a1/56a11f86-6f9f-4478-91ab-46c13503527b.png"></media:content><category>⭐ Проектирование КХД</category><tt:hashtag>dwh</tt:hashtag><tt:hashtag>кхд</tt:hashtag><tt:hashtag>проектирование_хранилищ</tt:hashtag><tt:hashtag>базы_данных</tt:hashtag><description><![CDATA[<img src="https://img2.teletype.in/files/91/0e/910ee527-f0e1-44f3-b0d2-d1507b007c0c.png"></img>КХД - корпоративное хранилище данных]]></description><content:encoded><![CDATA[
  <figure id="aVp2" class="m_column">
    <img src="https://img2.teletype.in/files/91/0e/910ee527-f0e1-44f3-b0d2-d1507b007c0c.png" width="1024" />
    <figcaption>Проектирование хранилища данных</figcaption>
  </figure>
  <blockquote id="eEtZ">КХД - корпоративное хранилище данных</blockquote>
  <nav>
    <ul>
      <li class="m_level_1"><a href="#YOnt">OLTP (On-line Transaction Processing) — Транзакционные системы</a></li>
      <li class="m_level_1"><a href="#GBm2">OLAP (On-line Analytical Processing) — Аналитические системы</a></li>
      <li class="m_level_1"><a href="#nbpL">📦 Что такое нормализация?</a></li>
      <li class="m_level_1"><a href="#pPBV">✅ 1NF (Первая нормальная форма) — “Ячейки = атомарные значения”</a></li>
      <li class="m_level_1"><a href="#Qkw7">✅ 2NF (Вторая нормальная форма) — “Убираем зависимости не от всего ключа”</a></li>
      <li class="m_level_1"><a href="#rnlS">✅ 3NF (Третья нормальная форма) — “Нет зависимостей между неключевыми полями”</a></li>
      <li class="m_level_1"><a href="#LEug">✅ BCNF (Нормальная форма Бойса-Кодда) — "Все детерминанты — ключи"</a></li>
      <li class="m_level_1"><a href="#WCdb">✅ 4NF (Четвёртая нормальная форма) — "Нет многозначных зависимостей"</a></li>
      <li class="m_level_1"><a href="#He0f">✅ 5NF (Пятая нормальная форма) — "Разложение без потерь"</a></li>
      <li class="m_level_1"><a href="#y4nB">✅ 6NF (Шестая нормальная форма) — "Минимальные атомы, с учётом времени"</a></li>
      <li class="m_level_1"><a href="#GTSM">Схема-звезда (Dimensional Modeling / Kimball)</a></li>
      <li class="m_level_1"><a href="#hVNr">Корпоративное информационное хранилище (Corporate Information Factory / Inmon)</a></li>
      <li class="m_level_1"><a href="#n1AH">Data Vault</a></li>
      <li class="m_level_2"><a href="#GvkI">Как всё это связано с паттернами КХД?</a></li>
      <li class="m_level_2"><a href="#DUZd">Итоговая схема:</a></li>
      <li class="m_level_1"><a href="#ruu5">⚙️ПРАКТИКА проектирование хранилища</a></li>
      <li class="m_level_2"><a href="#TGnH">Сценарий</a></li>
      <li class="m_level_2"><a href="#k7QA">Шаг 1: Идентификация бизнес-ключей</a></li>
      <li class="m_level_2"><a href="#IVvY">Шаг 2: Проектирование Хабов (Hubs)</a></li>
      <li class="m_level_2"><a href="#GLnP">Шаг 3: Проектирование Линков (Links)</a></li>
      <li class="m_level_2"><a href="#0rNz">Шаг 4: Проектирование Сателлитов (Satellites)</a></li>
      <li class="m_level_2"><a href="#AKfO">Как это работает на практике?</a></li>
      <li class="m_level_2"><a href="#O4rt">Что дальше? (Слой витрин данных)</a></li>
    </ul>
  </nav>
  <p id="DknL">✒️ <a href="https://t.me/+MgheIXzljMozYzJi" target="_blank">Автор</a></p>
  <p id="kIuJ">Представьте себе два разных мира баз данных: мир быстрых операций и мир глубокого анализа. Инженер данных строит мост (ETL/ELT-процессы) из мира OLTP в мир OLAP. </p>
  <section style="background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="AiWe"><strong>OLTP</strong> — это про запись данных, <strong>OLAP</strong> — про их чтение и анализ.</p>
  </section>
  <h3 id="YOnt"><strong>OLTP (On-line Transaction Processing) — Транзакционные системы</strong></h3>
  <ul id="qhPv">
    <li id="ZVfn"><strong>Что это?</strong> Это системы, которые обслуживают текущую деятельность бизнеса: кассовый аппарат в магазине, банковское приложение, система бронирования билетов.</li>
    <li id="TF1o"><strong>Задача:</strong> Быстро и надежно выполнять множество мелких операций (запись, изменение, удаление). Например: &quot;Продать товар X&quot;, &quot;Перевести 100 рублей со счета A на счет B&quot;.</li>
    <li id="NHUr"><strong>Ключевая особенность:</strong> Данные здесь <strong>максимально нормализованы</strong>. Это критично для целостности данных и избегания аномалий при частых изменениях. OLTP-системы — это и есть те самые <strong>источники данных</strong> для хранилища.</li>
  </ul>
  <h3 id="GBm2"><strong>OLAP (On-line Analytical Processing) — Аналитические системы</strong></h3>
  <ul id="jWJu">
    <li id="390y"><strong>Что это?</strong> Это и есть наши хранилища данных (КХД) и витрины данных.</li>
    <li id="uAJ9"><strong>Задача:</strong> Быстро выполнять сложные запросы на больших объемах исторических данных. Например: &quot;Показать средний чек по всем магазинам за последний год с разбивкой по категориям товаров и регионам&quot;.</li>
    <li id="oyZk"><strong>Ключевая особенность:</strong> Данные здесь часто <strong>денормализованны</strong> (как в схеме &quot;звезда&quot;), чтобы избежать медленных соединений (JOIN) множества таблиц и ускорить агрегацию.</li>
  </ul>
  <figure id="oME6" class="m_column">
    <img src="https://img3.teletype.in/files/6f/08/6f0809c9-9830-4461-a7ba-f9b1d8645f49.png" width="1024" />
    <figcaption>OLTP vs OLAP</figcaption>
  </figure>
  <hr />
  <h3 id="nbpL">📦 Что такое нормализация?</h3>
  <p id="KzDt">Нормализация — это <strong>набор правил (форм нормализации)</strong>, которые помогают организовать таблицы так, чтобы:</p>
  <ul id="Dk0X">
    <li id="bf4a"><strong>исключить дублирование данных</strong> (redundancy),</li>
    <li id="Xy51"><strong>избежать аномалий</strong> при вставке, обновлении или удалении (insertion/update/delete anomalies),</li>
    <li id="8LT5">упростить сопровождение хранилища.</li>
  </ul>
  <hr />
  <h3 id="pPBV">✅ 1NF (Первая нормальная форма) — “<strong>Ячейки = атомарные значения</strong>”</h3>
  <p id="Yiei">📌 <strong>Правило:</strong></p>
  <ul id="0BdV">
    <li id="Z4by">В таблице <strong>нет повторяющихся групп столбцов</strong>,</li>
    <li id="7c5E">В каждой ячейке — <strong>одно значение</strong>, а не список.</li>
  </ul>
  <p id="Sg8p">🔍 <strong>Пример плохой таблицы:</strong><br /></p>
  <figure id="F9M1" class="m_original">
    <img src="https://img2.teletype.in/files/5c/e0/5ce09992-b6dc-479f-bda7-aecec036efbb.png" width="266" />
  </figure>
  <p id="QRg7">🔧 <strong>После нормализации (1NF):</strong></p>
  <figure id="jjzc" class="m_original">
    <img src="https://img4.teletype.in/files/f4/4c/f44c2fd9-3842-4dfc-9b12-1f4c6c6a3b0f.png" width="170" />
  </figure>
  <p id="b73x">📎 То есть — <strong>разбиваем списки по строкам</strong>.</p>
  <hr />
  <h3 id="Qkw7">✅ 2NF (Вторая нормальная форма) — “<strong>Убираем зависимости не от всего ключа</strong>”</h3>
  <p id="Bvw8">📌 <strong>Правило:</strong></p>
  <ul id="wReN">
    <li id="i3dG">Уже есть 1NF.</li>
    <li id="f38Q">Все <strong>неключевые поля</strong> зависят от <strong>всего составного ключа</strong>, а не его части.</li>
  </ul>
  <p id="g073">🔍 <strong>Плохой пример:</strong></p>
  <figure id="biJp" class="m_original">
    <img src="https://img1.teletype.in/files/01/8e/018e2e2e-3ba9-4c33-9e47-dabbb1edbbda.png" width="424" />
  </figure>
  <p id="3Q0p">🔧 Проблема: <code>имя_клиента</code> зависит только от <code>заказ_id</code>, а не от пары (<code>заказ_id</code>, <code>товар</code>).</p>
  <p id="5zxB">✅ Надо вынести клиента в отдельную таблицу:</p>
  <p id="Qlyp"><strong>Таблица “заказы”</strong></p>
  <figure id="534l" class="m_original">
    <img src="https://img1.teletype.in/files/49/5d/495deb8b-886a-49eb-8dd2-de165e7a5052.png" width="219" />
  </figure>
  <p id="NKFb"><strong>Таблица “товары в заказах”</strong></p>
  <figure id="gDMp" class="m_original">
    <img src="https://img4.teletype.in/files/7d/44/7d44fa98-87a0-47f6-a3db-e28fa89260ea.png" width="345" />
  </figure>
  <hr />
  <h3 id="rnlS">✅ 3NF (Третья нормальная форма) — “Нет зависимостей между неключевыми полями”</h3>
  <p id="bzmO">📌 <strong>Правило:</strong></p>
  <ul id="JIMD">
    <li id="W3hy">Уже есть 2NF.</li>
    <li id="tYkQ">Никакое неключевое поле <strong>не зависит от другого неключевого</strong>.</li>
  </ul>
  <p id="BZbh">🔍 <strong>Плохой пример:</strong></p>
  <figure id="gtRW" class="m_original">
    <img src="https://img1.teletype.in/files/43/ab/43ab1e6b-c36d-4a50-804a-eacea50f1cc7.png" width="277" />
  </figure>
  <p id="o4a0">🔧 Проблема: <code>индекс</code> зависит от <code>город</code>, а не от <code>клиент_id</code>.</p>
  <p id="csQa">✅ Надо вынести справочник городов:</p>
  <p id="G90h"><strong>Таблица “клиенты”</strong></p>
  <figure id="Bz6f" class="m_original">
    <img src="https://img2.teletype.in/files/52/65/5265fe07-02c9-4347-a7f8-0020edd991bd.png" width="182" />
  </figure>
  <p id="KIMY"><strong>Таблица “города”</strong></p>
  <figure id="Nv6Q" class="m_original">
    <img src="https://img4.teletype.in/files/34/bb/34bb5a4f-4120-4239-8388-fb5eb2de965b.png" width="183" />
  </figure>
  <hr />
  <h3 id="LEug">✅ <strong>BCNF (Нормальная форма Бойса-Кодда)</strong> — <em>&quot;Все детерминанты — ключи&quot;</em></h3>
  <p id="ajEY">📌 Отличие от 3NF:</p>
  <ul id="EDST">
    <li id="stlN">3NF допускает, что детерминант (определяющее поле) не обязательно ключ, если зависимое поле — ключ.</li>
    <li id="SIuP">В BCNF — <strong>всё, что определяет другие поля, должно быть кандидатом в ключ</strong>.</li>
  </ul>
  <p id="zraX">🔍 Пример (тонкий случай):</p>
  <figure id="8y3i" class="m_original">
    <img src="https://img1.teletype.in/files/4a/aa/4aaae233-909b-4dcd-8417-4f45699f4b49.png" width="352" />
  </figure>
  <ul id="skuJ">
    <li id="4jnZ"><code>преподаватель → предмет</code>, <code>аудитория → предмет</code>, но ни <code>преподаватель</code>, ни <code>аудитория</code> не являются уникальными ключами.</li>
  </ul>
  <hr />
  <h3 id="WCdb">✅ <strong>4NF (Четвёртая нормальная форма)</strong> — <em>&quot;Нет многозначных зависимостей&quot;</em></h3>
  <p id="pEjj">📌 Когда один ключ связан с <strong>несколькими независимыми наборами данных</strong>.</p>
  <p id="7ptv">🔍 Пример:</p>
  <figure id="2lgp" class="m_original">
    <img src="https://img1.teletype.in/files/80/f3/80f34207-3167-4406-ab51-0d5cfcaab541.png" width="425" />
  </figure>
  <p id="gMum">→ Здесь <code>студент → курс</code> и <code>студент → кружок</code>, но курс и кружок <strong>не зависят друг от друга</strong>.</p>
  <p id="oHAE">🔧 Надо разнести в две таблицы:</p>
  <ul id="FdD5">
    <li id="NuZi">Таблица “студенты-курсы”</li>
    <li id="BNan">Таблица “студенты-кружки”</li>
  </ul>
  <hr />
  <h3 id="He0f">✅ <strong>5NF (Пятая нормальная форма)</strong> — <em>&quot;Разложение без потерь&quot;</em></h3>
  <p id="nSw6">📌 Сложные связи, когда таблица делится <strong>на 3 и более</strong> таблиц, но при этом при соединении <strong>ничего не теряется</strong> и не дублируется.</p>
  <p id="3aMK">🔍 Пример: если есть тройная связь <strong>Поставщик — Деталь — Проект</strong>, и всё работает только в этой тройке, а не по парам.</p>
  <ul id="i5do">
    <li id="rAnj">Нельзя просто разделить по парам <code>Поставщик-Деталь</code>, <code>Поставщик-Проект</code>, <code>Деталь-Проект</code> — <strong>некоторые комбинации не будут существовать</strong>.</li>
  </ul>
  <hr />
  <h3 id="y4nB">✅ <strong>6NF (Шестая нормальная форма)</strong> — <em>&quot;Минимальные атомы, с учётом времени&quot;</em></h3>
  <p id="AFsD">📌 Самая формальная форма. Применяется, когда данные часто <strong>меняются со временем</strong>, и <strong>каждое значение нужно отслеживать отдельно по времени</strong>.</p>
  <p id="i9x6">🔧 Каждое значение — в своей таблице, с временными метками (<code>valid_from</code>, <code>valid_to</code>).</p>
  <p id="cKMR">🧠 Это чаще используется:</p>
  <ul id="E3IJ">
    <li id="CMRi">в <strong>temporal databases</strong></li>
    <li id="I9dt">для <strong>декомпозиции фактов</strong> в хранилищах</li>
    <li id="R3BT">при работе с <strong>медленно меняющимися измерениями (SCD)</strong></li>
  </ul>
  <hr />
  <p id="RwqL">Для инженера данных ключевое значение имеют три основных подхода к проектированию хранилищ данных (КХД): <strong>моделирование по Кимбаллу (Kimball)</strong>, <strong>подход Инмона (Inmon)</strong> и <strong>Data Vault</strong>. Каждый из них предлагает свою структуру и философию организации данных для аналитики.</p>
  <hr />
  <h2 id="GTSM">Схема-звезда (Dimensional Modeling / Kimball)</h2>
  <p id="Q1Al">Это, пожалуй, самый популярный и практичный подход для инженеров данных. Его суть — создание простых и понятных структур, оптимизированных для быстрого выполнения запросов.</p>
  <ul id="hT9I">
    <li id="8EVY"><strong>Основная идея:</strong> Данные организуются в виде &quot;схемы-звезды&quot; (star schema) или &quot;снежинки&quot; (snowflake schema).</li>
    <ul id="aJFn">
      <li id="nWF7"><strong>Таблица фактов (Fact Table):</strong> В центре находится таблица с количественными показателями бизнеса (например, продажи, клики, транзакции). Она содержит числовые данные и ключи для связи с таблицами-измерениями.</li>
      <li id="ZCDD"><strong>Таблицы измерений (Dimension Tables):</strong> Это таблицы, которые описывают факты. Они содержат атрибуты, по которым можно фильтровать и группировать данные (например, клиенты, продукты, даты, география).</li>
    </ul>
    <li id="vhBv"><strong>Когда использовать:</strong> Идеально подходит для создания <strong>витрин данных (Data Marts)</strong>, ориентированных на конкретные бизнес-процессы (маркетинг, продажи, финансы). Отлично работает, когда бизнес-пользователям нужен быстрый и лёгкий доступ к данным для отчётности и BI-аналитики.</li>
    <li id="asDT"><strong>Преимущества:</strong></li>
    <ul id="A5sT">
      <li id="kE6Q"><strong>Простота:</strong> Модель интуитивно понятна бизнес-пользователям.</li>
      <li id="zFib"><strong>Производительность:</strong> Оптимизирована для чтения и агрегации, что ускоряет выполнение запросов.</li>
      <li id="9X4s"><strong>Гибкость:</strong> Легко добавлять новые атрибуты и показатели.</li>
    </ul>
    <li id="jKwM"><strong>Недостатки:</strong></li>
    <ul id="86G4">
      <li id="PxYN"><strong>Избыточность данных:</strong> Денормализация приводит к повторению данных в измерениях.</li>
      <li id="ra8X"><strong>Сложность интеграции:</strong> Объединение данных из разных &quot;звёзд&quot; может быть затруднительным, что усложняет получение единой картины по всей компании.</li>
    </ul>
  </ul>
  <p id="xM5I"><em><strong>Пример:</strong> Таблица фактов <code>Sales</code> с колонками <code>product_key</code>, <code>customer_key</code>, <code>date_key</code>, <code>amount</code> и таблицы измерений <code>DimProduct</code>, <code>DimCustomer</code>, <code>DimDate</code>.</em>**</p>
  <hr />
  <h2 id="hVNr">Корпоративное информационное хранилище (Corporate Information Factory / Inmon)</h2>
  <p id="vGeh">Этот подход более академичен и направлен на создание единого, целостного источника правды для всей организации.</p>
  <ul id="WM4V">
    <li id="bicb"><strong>Основная идея:</strong> Проектирование &quot;сверху вниз&quot;. Сначала все данные из разных источников интегрируются в централизованное хранилище данных (Enterprise Data Warehouse, EDW). Это хранилище находится в <strong>третьей нормальной форме (3NF)</strong>, что устраняет избыточность данных. Уже из этого центрального хранилища создаются витрины данных (Data Marts) для конкретных отделов.</li>
    <li id="O3wA"><strong>Когда использовать:</strong> В крупных организациях со сложными и разнообразными источниками данных, где целостность и согласованность данных являются главным приоритетом.</li>
    <li id="Q2UA"><strong>Преимущества:</strong></li>
    <ul id="G4vZ">
      <li id="1SvM"><strong>Единый источник правды:</strong> Централизованное хранилище обеспечивает целостность и согласованность данных по всей компании.</li>
      <li id="nX97"><strong>Низкая избыточность:</strong> Нормализация минимизирует дублирование данных.</li>
      <li id="WY61"><strong>Гибкость:</strong> Легко создавать новые витрины данных для любых нужд.</li>
    </ul>
    <li id="0irx"><strong>Недостатки:</strong></li>
    <ul id="AgEI">
      <li id="neZF"><strong>Сложность и стоимость:</strong> Требует значительных начальных усилий и затрат на проектирование и загрузку данных в нормализованную модель.</li>
      <li id="5nUu"><strong>Медленные запросы к EDW:</strong> Запросы напрямую к центральному хранилищу могут быть медленными из-за большого количества соединений (JOINs). Аналитика обычно выполняется по витринам.</li>
    </ul>
  </ul>
  <hr />
  <h2 id="n1AH">Data Vault</h2>
  <blockquote id="FrG7">Это гибридный подход, который пытается взять лучшее от моделей Кимбалла и Инмона. Он спроектирован для обеспечения гибкости, масштабируемости и аудируемости хранилища.</blockquote>
  <ul id="72Js">
    <li id="ki2w"><strong>Основная идея:</strong> Модель состоит из трёх основных типов таблиц:</li>
    <ul id="vyvx">
      <li id="gdIG"><strong>Хабы (Hubs):</strong> Содержат уникальные бизнес-ключи (например, <code>customer_id</code>, <code>product_number</code>). Они определяют основные бизнес-сущности.</li>
      <li id="23fv"><strong>Линки (Links):</strong> Определяют связи между хабами. По сути, это таблицы связей &quot;многие-ко-многим&quot;.</li>
      <li id="fkn7"><strong>Саттелиты (Satellites):</strong> Хранят описательные атрибуты хабов и линков, а также историю их изменений. Каждый саттелит содержит данные из одного источника.</li>
    </ul>
    <li id="29HF"><strong>Когда использовать:</strong> В средах, где источники данных часто меняются, требования к данным постоянно эволюционируют, и важна полная отслеживаемость (аудируемость) данных. Отлично подходит для построения <strong>&quot;сырого&quot; слоя (Raw DWH)</strong>.</li>
    <li id="vMI7"><strong>Преимущества:</strong></li>
    <ul id="mjB1">
      <li id="hDsc"><strong>Гибкость и масштабируемость:</strong> Легко добавлять новые источники данных, не перестраивая существующую модель.</li>
      <li id="XIdm"><strong>Аудируемость:</strong> Структура позволяет отслеживать, откуда и когда поступили данные.</li>
      <li id="usN1"><strong>Параллельная загрузка:</strong> Компоненты модели (хабы, линки, саттелиты) можно загружать независимо и параллельно.</li>
    </ul>
    <li id="DJ6b"><strong>Недостатки:</strong></li>
    <ul id="J91Q">
      <li id="nbEQ"><strong>Сложность для конечных пользователей:</strong> Модель не предназначена для прямых запросов от бизнес-аналитиков. Требует создания витрин данных (в виде схемы-звезды) поверх Data Vault для аналитики.</li>
      <li id="tgDE"><strong>Большое количество таблиц:</strong> Модель генерирует много таблиц и соединений, что усложняет её понимание.</li>
    </ul>
  </ul>
  <hr />
  <h3 id="GvkI">Как всё это связано с паттернами КХД?</h3>
  <p id="hE6l">Теперь сложим пазл:</p>
  <ul id="ZqbM">
    <li id="Bu7S"><strong>Подход Инмона (Inmon):</strong></li>
    <ul id="jMRU">
      <li id="ciyv">Берет данные из <strong>OLTP-систем</strong>.</li>
      <li id="A7GT">Строит центральное хранилище (EDW) по принципам <strong>OLTP</strong> — в <strong>третьей нормальной форме (3НФ)</strong>. Цель — создать единый, целостный источник правды без избыточности.</li>
      <li id="UQSn">Уже из этого нормализованного хранилища строятся <strong>OLAP</strong>-витрины (часто в виде схемы &quot;звезда&quot;) для аналитиков.</li>
    </ul>
    <li id="vTKC"><strong>Подход Кимбалла (Kimball):</strong></li>
    <ul id="SWsS">
      <li id="DvT4">Берет данные из <strong>OLTP-систем</strong>.</li>
      <li id="X0oR">Сразу строит <strong>OLAP</strong>-витрины (схема &quot;звезда&quot;). Для этого он намеренно <strong>ОТКАЗЫВАЕТСЯ</strong> от 3НФ и <strong>денормализует</strong> данные. Атрибуты (например, название категории товара) копируются прямо в таблицу измерений продуктов, чтобы избежать лишних JOIN&#x27;ов при запросе.</li>
      <li id="w6Dp">Это осознанный компромисс: жертвуем эффективностью хранения ради скорости анализа.</li>
    </ul>
    <li id="TUr9"><strong>Data Vault:</strong></li>
    <ul id="dvcF">
      <li id="mF3y">Это гибрид, который интересно использует нормализацию.</li>
      <li id="esDe"><strong>Хабы</strong> (бизнес-ключи) и <strong>Линки</strong> (связи) очень похожи на нормализованную структуру. Здесь нет избыточности ключей и связей.</li>
      <li id="FgzP">А вот <strong>Саттелиты</strong>, хранящие атрибуты и их историю, концептуально близки к <strong>шестой нормальной форме (6НФ)</strong>. Каждый саттелит хранит историю изменений атрибутов из одного источника, что позволяет детально отслеживать их во времени, как и предполагает 6НФ.</li>
      <li id="s5H0">Data Vault сам по себе не является <strong>OLAP</strong>-системой. Поверх него, как и в подходе Инмона, строят <strong>OLAP</strong>-витрины по Кимбаллу.</li>
    </ul>
  </ul>
  <h3 id="DUZd">Итоговая схема:</h3>
  <ol id="j6vc">
    <li id="YCbv"><strong>Источник:</strong> <strong>OLTP</strong>-системы (базы данных приложений, CRM, ERP), спроектированные в <strong>3НФ</strong>.</li>
    <li id="xOxy"><strong>Трансформация (ETL/ELT):</strong> Инженер данных забирает данные и преобразует их.</li>
    <li id="HFhS"><strong>Хранилище (КХД):</strong></li>
    <ul id="6C5N">
      <li id="FI2m"><strong>Инмон:</strong> Сначала в <strong>3НФ</strong>, потом в денормализованные витрины.</li>
      <li id="Jn4w"><strong>Кимбалл:</strong> Сразу в денормализованные витрины (схема &quot;звезда&quot;).</li>
      <li id="RV2Y"><strong>Data Vault:</strong> В гибридную модель (Хабы/Линки/Саттелиты), которая похожа на смесь нормализации и <strong>6НФ</strong>.</li>
    </ul>
    <li id="NbEa"><strong>Цель:</strong> Предоставить данные для <strong>OLAP</strong> — быстрого и удобного анализа.</li>
  </ol>
  <hr />
  <figure id="iegx" class="m_column">
    <img src="https://img1.teletype.in/files/84/5b/845b189b-38db-419d-b1fa-9cbab035ff8f.png" width="1024" />
  </figure>
  <h2 id="ruu5"><strong>⚙️ПРАКТИКА</strong> проектирование хранилища</h2>
  <blockquote id="CbVo">Давайте спроектируем хранилище по методологии Data Vault для реального и понятного бизнеса — <strong>интернет-магазина</strong>.</blockquote>
  <h3 id="TGnH">Сценарий</h3>
  <ul id="Uxv6">
    <li id="VyFM"><strong>Бизнес:</strong> Интернет-магазин &quot;ТехноМир&quot;, продающий электронику.</li>
    <li id="P7C2"><strong>Источники данных:</strong></li>
    <ol id="XmZc">
      <li id="sScS"><strong>CRM-система:</strong> Информация о клиентах.</li>
      <li id="NMM9"><strong>Система обработки заказов (Sales DB):</strong> Данные о заказах и их составе.</li>
      <li id="CxWq"><strong>Каталог товаров (PIM - Product Information Management):</strong> Информация о продуктах.</li>
    </ol>
    <li id="2S7g"><strong>Наша задача:</strong> Построить &quot;сырой&quot; слой хранилища (Raw Data Vault), который интегрирует данные из этих систем, сохраняя всю историю изменений.</li>
  </ul>
  <hr />
  <h3 id="k7QA">Шаг 1: Идентификация бизнес-ключей</h3>
  <p id="u5qb">Сначала мы находим уникальные, стабильные идентификаторы, которые бизнес использует для отслеживания своих ключевых сущностей. Это &quot;гвозди&quot;, на которых будет держаться вся модель.</p>
  <ul id="YT5t">
    <li id="BgQw"><code>customer_id</code> — Уникальный номер клиента в CRM.</li>
    <li id="BhrG"><code>order_number</code> — Уникальный номер заказа.</li>
    <li id="boXU"><code>product_sku</code> — Артикул товара, уникальный идентификатор продукта.</li>
  </ul>
  <hr />
  <h3 id="IVvY">Шаг 2: Проектирование Хабов (Hubs)</h3>
  <p id="sznv">Хабы — это таблицы, хранящие <strong>только</strong> бизнес-ключи. Они являются якорями для наших бизнес-сущностей.</p>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="CVcw">HUB_CUSTOMER (Клиенты)</p>
  </section>
  <figure id="6EVg" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_CUSTOMER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Хэш от customer_id. Первичный ключ.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>customer_id</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(50)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Бизнес-ключ из CRM.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата загрузки записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;CRM&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="BsI3">HUB_ORDER (Заказы)</p>
  </section>
  <figure id="Oj6K" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_ORDER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Хэш от order_number.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>order_number</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(50)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Бизнес-ключ из Sales DB.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата загрузки записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;SalesDB&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="gFms">HUB_PRODUCT (Товары)</p>
  </section>
  <figure id="RkBB" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_PRODUCT_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Хэш от product_sku.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>product_sku</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(50)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Бизнес-ключ из PIM.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата загрузки записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;PIM&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <hr />
  <h3 id="GLnP">Шаг 3: Проектирование Линков (Links)</h3>
  <p id="Fc5O">Линки — это таблицы, которые определяют связи между хабами. Они не хранят никаких атрибутов, только хэш-ключи хабов, которые они соединяют.</p>
  <section style="background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="2xKW">LNK_CUSTOMER_ORDER (Связь &quot;Клиент сделал Заказ&quot;)</p>
  </section>
  <figure id="5Ser" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>L_CUSTOMER_ORDER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Хэш от конкатенации H_CUSTOMER_HK и H_ORDER_HK.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_CUSTOMER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>FK. Ссылка на HUB_CUSTOMER.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_ORDER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>FK. Ссылка на HUB_ORDER.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата загрузки записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;SalesDB&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="smZk">LNK_ORDER_PRODUCT (Связь &quot;Заказ содержит Товар&quot;)</p>
  </section>
  <figure id="9t9e" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>L_ORDER_PRODUCT_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Хэш от конкатенации H_ORDER_HK и H_PRODUCT_HK.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_ORDER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>FK. Ссылка на HUB_ORDER.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_PRODUCT_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>FK. Ссылка на HUB_PRODUCT.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата загрузки записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;SalesDB&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <hr />
  <h3 id="0rNz">Шаг 4: Проектирование Сателлитов (Satellites)</h3>
  <p id="6p7J">Сателлиты — это таблицы, которые хранят описательные, изменяющиеся во времени атрибуты. Они &quot;висят&quot; на хабах или линках и отслеживают всю историю изменений.</p>
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="Ve2W">SAT_CUSTOMER_DETAILS (Детали о клиенте)</p>
  </section>
  <figure id="dYGY" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_CUSTOMER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK, FK. Ссылка на HUB_CUSTOMER.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Дата загрузки этой версии записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>HashDiff</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Хэш от атрибутов для быстрого обнаружения изменений.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>first_name</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(100)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя клиента.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>email</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(100)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Электронная почта.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>registration_date</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATE</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата регистрации.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;CRM&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="AOAT">SAT_ORDER_DETAILS (Детали о заказе)</p>
  </section>
  <figure id="UdXB" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_ORDER_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK, FK. Ссылка на HUB_ORDER.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Дата загрузки этой версии записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>HashDiff</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Хэш от атрибутов.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>order_date</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Дата и время заказа.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>order_status</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(20)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Статус (напр., &#x27;Processing&#x27;, &#x27;Shipped&#x27;).</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>shipping_address</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(255)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Адрес доставки.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;SalesDB&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="LAQb">SAT_PRODUCT_DETAILS (Детали о товаре)</p>
  </section>
  <figure id="xCA4" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>H_PRODUCT_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK, FK. Ссылка на HUB_PRODUCT.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Дата загрузки этой версии записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>HashDiff</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Хэш от атрибутов.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>product_name</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(255)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Название товара.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>category</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(100)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Категория.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>price</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DECIMAL(10,2)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Текущая цена.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;PIM&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="AGwM">SAT_LNK_ORDER_PRODUCT_DETAILS (Детали о строке заказа)</p>
  </section>
  <figure id="C3VS" class="m_column">
    <iframe srcdoc="<table style=&quot;border-collapse: collapse; width: 100%;&quot;>
  <thead>
    <tr style=&quot;background-color: #f2f2f2;&quot;>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Имя столбца</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Тип</th>
      <th style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Описание</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>L_ORDER_PRODUCT_HK</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK, FK. Ссылка на LNK_ORDER_PRODUCT.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>LoadDate</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DATETIME</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>PK. Дата загрузки этой версии записи.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>HashDiff</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>BINARY(16)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Хэш от атрибутов.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>quantity</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>INT</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Количество товара в заказе.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>price_per_item</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>DECIMAL(10,2)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Цена за единицу в момент заказа.</td>
    </tr>
    <tr>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>RecordSource</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>VARCHAR(10)</td>
      <td style=&quot;border: 1px solid #ccc; padding: 8px;&quot;>Источник (напр., &#x27;SalesDB&#x27;).</td>
    </tr>
  </tbody>
</table>"></iframe>
  </figure>
  <hr />
  <h3 id="AKfO">Как это работает на практике?</h3>
  <p id="pAFT">Представим, что <strong>25.07.2025</strong> новый клиент <code>C123</code> (Иван) делает заказ <code>ORD987</code> на 2 смартфона <code>SKU-XYZ</code>.</p>
  <ol id="mihq">
    <li id="ih8J"><strong>Загрузка в Хабы:</strong></li>
    <ul id="z8xp">
      <li id="Gbhe">В <code>HUB_CUSTOMER</code> добавляется запись с <code>customer_id = &#x27;C123&#x27;</code>.</li>
      <li id="QT5a">В <code>HUB_ORDER</code> добавляется запись с <code>order_number = &#x27;ORD987&#x27;</code>.</li>
      <li id="l4y4">В <code>HUB_PRODUCT</code> добавляется запись с <code>product_sku = &#x27;SKU-XYZ&#x27;</code> (если ее там еще нет).</li>
    </ul>
    <li id="RmUN"><strong>Загрузка в Линки:</strong></li>
    <ul id="MmgX">
      <li id="k817">В <code>LNK_CUSTOMER_ORDER</code> создается связь между хэшами клиента <code>C123</code> и заказа <code>ORD987</code>.</li>
      <li id="pRaf">В <code>LNK_ORDER_PRODUCT</code> создается связь между хэшами заказа <code>ORD987</code> и продукта <code>SKU-XYZ</code>.</li>
    </ul>
    <li id="KZ7L"><strong>Загрузка в Сателлиты:</strong></li>
    <ul id="6twu">
      <li id="IRSW">В <code>SAT_CUSTOMER_DETAILS</code> добавляется запись с именем &quot;Иван&quot; и его email, привязанная к хэшу клиента <code>C123</code>.</li>
      <li id="Vy5w">В <code>SAT_ORDER_DETAILS</code> добавляется запись со статусом &quot;Processing&quot; и адресом доставки, привязанная к хэшу заказа <code>ORD987</code>.</li>
      <li id="dg9l">В <code>SAT_LNK_ORDER_PRODUCT_DETAILS</code> добавляется запись с <code>quantity = 2</code>, привязанная к хэшу связи заказа и товара.</li>
    </ul>
  </ol>
  <p id="lQip"><strong>Что если клиент изменит email?</strong> При следующей загрузке данных система вычислит новый <code>HashDiff</code> для атрибутов клиента. Так как он не совпадет со старым, в <code>SAT_CUSTOMER_DETAILS</code> будет добавлена <strong>новая строка</strong> с тем же <code>H_CUSTOMER_HK</code>, но новой <code>LoadDate</code> и новым email. Старая запись останется нетронутой. <strong>Мы сохранили историю!</strong></p>
  <h3 id="O4rt">Что дальше? (Слой витрин данных)</h3>
  <p id="a9ar">Эта структура идеальна для хранения и интеграции данных, но неудобна для прямого анализа. Поэтому следующим шагом инженер данных строит поверх этого &quot;сырого&quot; слоя <strong>витрину данных</strong> (Data Mart) в виде привычной <strong>схемы-звезды</strong>:</p>
  <ul id="fGse">
    <li id="PvNf"><strong>FactSales (Таблица фактов):</strong> Собирается из линков и их сателлитов. Будет содержать <code>H_CUSTOMER_HK</code>, <code>H_PRODUCT_HK</code>, <code>quantity</code>, <code>total_amount</code>.</li>
    <li id="RD7W"><strong>DimCustomer (Измерение клиентов):</strong> Собирается из <code>HUB_CUSTOMER</code> и его сателлита <code>SAT_CUSTOMER_DETAILS</code> (берется последняя, актуальная версия данных).</li>
    <li id="dcjh"><strong>DimProduct, DimDate и т.д.</strong></li>
  </ul>
  <p id="1t6X">Теперь бизнес-аналитики могут легко делать свои OLAP-запросы к этой простой и понятной &quot;звезде&quot;, а в основе у нас лежит надежное, аудируемое и гибкое хранилище Data Vault.</p>
  <hr />
  <section style="background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="WTA7">⚙️ Контент создается в рамках программы &quot;Базы знаний&quot; телеграмм канала &quot;Аналитик на минималках&quot; <a href="https://t.me/+MgheIXzljMozYzJi" target="_blank">https://t.me/+MgheIXzljMozYzJi</a></p>
  </section>
  <tt-tags id="IDQG">
    <tt-tag name="dwh">#dwh</tt-tag>
    <tt-tag name="кхд">#кхд</tt-tag>
    <tt-tag name="проектирование_хранилищ">#проектирование_хранилищ</tt-tag>
    <tt-tag name="базы_данных">#базы_данных</tt-tag>
  </tt-tags>

]]></content:encoded></item><item><guid isPermaLink="true">https://notes.darin.pro/vpn</guid><link>https://notes.darin.pro/vpn?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=darin.pro</link><comments>https://notes.darin.pro/vpn?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=darin.pro#comments</comments><dc:creator>darin.pro</dc:creator><title>VPN который работает всегда ✅</title><pubDate>Sat, 28 Jun 2025 07:55:42 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/b0/b6/b0b66875-064b-4582-8160-c10b3b558796.png"></media:content><category>Полезные сервисы и инструменты IT</category><tt:hashtag>vpn</tt:hashtag><tt:hashtag>it_инструменты</tt:hashtag><description><![CDATA[<img src="https://img1.teletype.in/files/c0/7d/c07d1470-d41f-4bad-af60-aba3664720dd.jpeg"></img>✒️ Автор]]></description><content:encoded><![CDATA[
  <figure id="ERtA" class="m_column">
    <img src="https://img1.teletype.in/files/c0/7d/c07d1470-d41f-4bad-af60-aba3664720dd.jpeg" width="1024" />
  </figure>
  <nav>
    <ul>
      <li class="m_level_1"><a href="#EIye">Как я его нашел</a></li>
      <li class="m_level_1"><a href="#8n6O">Преимущества HOUR VPN</a></li>
      <li class="m_level_1"><a href="#BPzo">Как использовать</a></li>
      <li class="m_level_1"><a href="#zp2p">Бонус 📌 Как использовать VPN бесплатно</a></li>
    </ul>
  </nav>
  <p id="6cNN">✒️ <a href="https://t.me/+MgheIXzljMozYzJi" target="_blank">Автор</a></p>
  <p id="HWvK">⚙️ <a href="https://t.me/hour_vpn_bot?start=KHcbgebBQh" target="_blank">Сервис VPN</a> </p>
  <hr />
  <blockquote id="5uGJ"><a href="https://t.me/hour_vpn_bot?start=KHcbgebBQh" target="_blank">ВПН</a> — это тот инструмент сейчас, без которого границы возможностей сужаются.</blockquote>
  <hr />
  <p id="FMQL">Я думаю многие из вас сталкивались с такими проблемами при подборе такого инструмента:</p>
  <ul id="ftH5">
    <li id="wS7M">перестает работать и приходится искать новый;</li>
    <li id="yay3">низкая скорость;</li>
    <li id="CJvB">если работает на компьютере, то как использовать на телефоне;</li>
    <li id="bely">платный и дорого, месячная подписка;</li>
    <li id="ml8W">утечка персональных данных.</li>
  </ul>
  <hr />
  <h2 id="EIye">Как я его нашел</h2>
  <p id="PApY">В рекомендациях ютуба мне подкинули видео &quot;как развернуть свой собственный vpn на удаленном сервере&quot;.</p>
  <section style="background-color:hsl(hsl(34,  84%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="ND9e">Сразу совет - смотрите, ищете материал только полезный для себя, не нужно искать новости, какой то треш, мемасики. Система запоминает ваши действия и начинает подкидывать соответствующий контент. </p>
  </section>
  <p id="cuSS">Я просмотрел это видео, и вот сразу видно, что оно заточено на полезность, а не на красивое оформление мусора. Автор именно показал все шаг за шагом и показал, что из этого должно получится, дал <a href="https://t.me/hour_vpn_bot?start=KHcbgebBQh" target="_blank">ссылку </a>на готовый инструмент.</p>
  <p id="aG36">А получился работающий сервис VPN с разными протоколами, с возможностью подключаться и через компьютер и через телефон а интерфейс взаимодействия через телеграмм бота.</p>
  <figure id="YuH3" class="m_original">
    <img src="https://img2.teletype.in/files/15/51/155176b9-bf72-4fdc-b987-877e9e660e95.png" width="484" />
    <figcaption>интерфейс телеграмм бота vpn</figcaption>
  </figure>
  <p id="8fPr">Так как видео автора были не особо красивыми и с кричащими заголовками, то просмотров у него было немного.</p>
  <p id="pt4r">Мои мысли на тот момент: </p>
  <ul id="nYgf">
    <li id="qmBY">мне нужен свой vpn или мне нужен инструмент, которым удобно пользоваться?</li>
    <li id="GbB3">мне важно пользоваться только тогда, когда он нужен или оплачивать работу сервера?</li>
  </ul>
  <hr />
  <h2 id="8n6O">Преимущества HOUR VPN</h2>
  <ol id="UGcO">
    <li id="zjod">Модель оплаты за 1 час</li>
    <li id="ZyB4">Низкая стоимость, всего 0,25 руб за 1 час использования. Или 6 руб в день за 1 ключ</li>
    <li id="VFpc">Возможность использовать бесплатно</li>
    <li id="PUpI">Выбирать сервер подключения автоматически, в зависимости от нагрузки</li>
    <li id="clwM">Мультиплатформенность (телефон, компьютер)</li>
    <li id="KPop">Управление через телеграмм бота</li>
    <li id="Q8Mq">Неограниченное количество ключей</li>
    <li id="6Ri2">Мульти скидки за пополнение и количество используемых ключей</li>
    <li id="wp9J">Бесперебойность работы</li>
    <li id="bJDY">Простота использования</li>
  </ol>
  <hr />
  <h2 id="BPzo">Как использовать</h2>
  <p id="xLpW">🟢 Перейти по ссылке - <a href="https://t.me/hour_vpn_bot?start=KHcbgebBQh" target="_blank">https://t.me/hour_vpn_bot?start=KHcbgebBQh</a></p>
  <p id="dEpI">Сразу получаете на баланс стартовый депозит 30 руб. Поверьте эти 30 руб можно использовать вечно 😜 читайте ниже инструкцию)</p>
  <p id="IhpA">Далее все интуитивно понятно &gt;&gt;&gt; <strong>Создать VPN 🔐</strong></p>
  <figure id="Shcm" class="m_original">
    <img src="https://img4.teletype.in/files/f7/97/f797b070-946f-4a22-8235-1e465a1d36e5.png" width="532" />
    <figcaption>выбор протокола VPN</figcaption>
  </figure>
  <p id="ddQV">Что удобно, что все расписано. Я предпочитаю не изобретать велосипед и выбираю современный и надежный протокол без блокировок от провайдеров VLESS.</p>
  <figure id="8023" class="m_original">
    <img src="https://img1.teletype.in/files/07/a3/07a383f8-f1fe-469c-bcbb-8a87cd61c2c7.png" width="545" />
    <figcaption>выбор страны VPN</figcaption>
  </figure>
  <p id="Q7VA">Рекомендованная страна обычно обозначается 👈</p>
  <p id="SEAg">Но по привычке я использую страну близлежайшую к себе, это Казахстан. Знаю что все популярные сервисы по типу чата GPT пускают без проблем.</p>
  <figure id="tYT0" class="m_original">
    <img src="https://img3.teletype.in/files/ab/3d/ab3de507-f159-4370-843b-1418423f94c3.png" width="543" />
    <figcaption>выбор сервера VPN</figcaption>
  </figure>
  <p id="gu27">Можно выбирать любой, либо довериться системе и она выберет менее нагруженный.</p>
  <figure id="hgj5" class="m_column">
    <img src="https://img3.teletype.in/files/ab/f1/abf1b5ba-ef83-4247-b207-76c7fc559bcf.png" width="811" />
    <figcaption>получение ключа доступа VPN</figcaption>
  </figure>
  <p id="blW7">Вот и получили на ключ доступа 🔑, а далее можно посмотреть по кнопкам на какой платформе мы будем его использовать и получить подробную инструкцию, как этим ключом пользоваться.</p>
  <blockquote id="8YtG">Вот например как это выглядит для WINDOWS:</blockquote>
  <figure id="u78i" class="m_original">
    <img src="https://img3.teletype.in/files/60/58/6058bdc5-75b8-48e4-b121-0e94ae291d36.png" width="585" />
  </figure>
  <figure id="7ix2" class="m_original">
    <img src="https://img3.teletype.in/files/62/76/6276a66e-7b2e-47c7-8a38-fe96cf01eae0.png" width="545" />
  </figure>
  <p id="dAoX">Даже саму программу не нужно искать где то, сам установщик уже приложен. А также все по шагам на скриншотах.</p>
  <hr />
  <h2 id="zp2p">Бонус 📌 Как использовать VPN бесплатно</h2>
  <p id="iNXP">Зачастую нам нужно что-то посмотреть, спросить у чата GPT или поработать с зарубежными сервисами всего пару часиков.</p>
  <section style="background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="t6V4">Так как оплата производится за 1 час использования и списывают 0,25 руб, то мы просто пользуемся меньше часа и пересоздаем ключ повторно 😉</p>
  </section>
  <ol id="Pap5">
    <li id="HetH">В главном меню нужно нажать на <strong>Мой VPN 🔑</strong></li>
    <li id="ezaL">Выбрать действующий ключ</li>
    <li id="4V2S">Нажать <strong>Удалить ключ 🚫 </strong>и подтвердить действие</li>
  </ol>
  <figure id="mLKs" class="m_column">
    <img src="https://img2.teletype.in/files/5e/c9/5ec901cd-7180-45c1-99b6-dbaa95af569d.png" width="766" />
  </figure>
  <hr />
  <section style="background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="WGR2">⚙️ Контент создается в рамках программы &quot;Базы знаний&quot; телеграмм канала &quot;Аналитик на минималках&quot; <a href="https://t.me/+MgheIXzljMozYzJi" target="_blank">https://t.me/+MgheIXzljMozYzJi</a></p>
  </section>
  <tt-tags id="RGeu">
    <tt-tag name="vpn">#vpn</tt-tag>
    <tt-tag name="it_инструменты">#it_инструменты</tt-tag>
  </tt-tags>

]]></content:encoded></item></channel></rss>