Показаны сообщения с ярлыком PostgreSQL. Показать все сообщения
Показаны сообщения с ярлыком PostgreSQL. Показать все сообщения

вторник, 10 марта 2026 г.

Загрузка изменений из двух источников в одну ДТФ

В статье о соединении диапазонных таблиц фактов (ДТФ) я рассмотрел запрос, формирующий из двух ДТФ корректный набор диапазонов с фактами из обеих таблиц.

Заметим, что

  1. составные первичные ключи в двух таблицах, включающие дату начала диапазона, могут занимать не меньше, а, возможно, и больше места, чем столбцы фактов,
  2. запрос, соединяющий миллионы (десятки, сотни миллионов) строк из двух ДТФ в любом случае будет ресурсоемким.

Если такой запрос требуется выполнять часто, то оказывается выгодно хранить факты, даже загружаемые из разных источников, не в двух, а в одной ДТФ.

суббота, 21 февраля 2026 г.

Загрузка изменений за прошлые даты в ДТФ

В посте о диапазонных таблицах фактов (ДТФ) я привел алгоритм их заполнения из ежедневных снэпшотов, содержащих данные на текущую дату. Алгоритм также годится для заполнения ДТФ в случае, когда на входе не регулярные (ежедневные) снэпшоты, а только нерегулярные изменения (дельта).

Но время от времени возникает задача добавления в непустую ДТФ новых или измененных данных за прошлые даты, и упомянутый алгоритм для этого не годится. Поэтому рассмотрим универсальный алгоритм заполнения ДТФ из источника, откуда поступают данные как на текущую дату, так и на прошлые даты — если данные за прошлую дату изменились.

вторник, 26 августа 2025 г.

Соединение диапазонных таблиц фактов

В прошлый раз я описал компактную форму хранения нерегулярно меняющихся данных в диапазонной таблице фактов (ДТФ) на основе периодических снэпшотов.

Речь идет о таблице фактов в широком смысле:

"Каждая таблица с составным ключом из нескольких внешних ключей – это таблица фактов." Ральф Кимбалл

Такая таблица не обязательно принадлежит презентационному слою хранилища данных, но на законных основаниях может жить в промежуточном слое, который предоставляет данные для витрин. (Кстати, такая таблица в терминах Data Vault — сателлит линка.)

воскресенье, 4 мая 2025 г.

Компактное представление истории нерегулярно меняющихся данных

Тема данного поста навеяна чтением Ральфа Кимбалла, который выделяет три вида таблиц фактов при построении хранилищ данных: транзакционные, снэпшотные и накопительные. В первых каждой строке соответствует отдельная транзакция (бизнес-операция, факт снятия показаний, зарегистрированное уникальное событие), загружаемая в хранилище данных из системы-источника. Вторые формруются из периодически загружаемых моментальных снимков (снэпшотов), где каждый снэпшот содержит множество строк. Третьи допускают многократное обновление строк, поскольку их строки описывают некие эволюционирующие сущности, например, заказы с этапами жизненного цикла или продажи за месяц при ежедневном обновлении.

Поговорим о снэпшотных таблицах фактов. И начнем с определения контекста.

среда, 13 марта 2024 г.

Оконные функции aka over-функции

Если бы у нас были только агрегатные функции, мы были бы принуждены постоянно делать выбор: видеть детальные данные или агрегированные? Аналитические функции, известные также как оконные функции или over-функции, позволяют одновременно получить и то и другое. С их помощью можно видеть данные, агрегированные по множеству строк, рядом с детальными данными.

Обычные, или скалярные, функции принимают на вход значения столбцов одной — текущей — строки курсора. Агрегатные функции принимают на вход значения столбцов всех строк курсора, определяемых where и group by (или их отсутствием). Оконные функции принимают на вход значения столбцов множества строк, определяемого в предложении over и зависящего от текущей строки.

Рассмотрим оконные функции на примере СУБД PosgreSQL 15.

четверг, 7 марта 2024 г.

Пробелы и острова, или Gaps and islands. Часть II

Это продолжение поста Пробелы и острова, или Gaps and islands. Часть I

Напомню, что задачи вида "пробелы и острова", или "gaps and islands", возникают, когда в некоторой последовательности нужно найти участки (диапазоны, интервалы) непрерывных данных – "острова" – и/или участки отсутствия данных – "пробелы".

Часто последовательность данных – это хронологическая последовательность, то есть, развернутая во времени, например, по датам. Тогда "острова" – это непрерывные периоды, когда некое событие происходит ежедневно, а "пробелы" – это непрерывные периоды, в течение которых это событие не происходит.

Рассмотрим решение задачи "пробелы и острова" на хронологической последовательности данных.

Пробелы и острова, или Gaps and islands. Часть I

Задачи вида "пробелы и острова", или "gaps and islands", возникают, когда в некоторой последовательности нужно найти участки (диапазоны, интервалы) непрерывных данных – "острова" – и/или участки отсутствия данных – "пробелы".

С наступленим эры оконных функций (они же аналитические, они же over-функции) задачи вида "пробелы и острова" решаются с помощью этих функций.

Примеры ниже с таблицей t1 взяты мной из статьи Solving Gaps and Islands with Enhanced Window Functions by Itzik Ben-Gan и адаптированы для выполнения на PostgreSQL.

После примеров с таблицей t1 я разберу более прикладной оригинальный пример с таблицей ежедневных продаж daily_sales.

понедельник, 26 февраля 2024 г.

Периодические таблицы-2 (не химия)

В посте Периодические таблицы (не химия) я писал о специфике работы с таблицами, строки которых содержат период действия. В частности, рассматривал способы обеспечения того, чтобы периоды не перекрывались. При этом периоды действия определялись двумя полями: первая дата действия и последняя дата действия, где обе даты включены в период. Такой подход позволяет выбирать действующую строку с помощью оператора between, как в следующем примере:

select *
from ttt
where current_date between first_date and last_date
;

Подход естественный и очевидный. В самом деле, январь длится с 1 по 31, включительно. Неделя длится с понедельника по воскресенье, включительно. Акция в магазине проходит с 10 по 15 апреля, включительно.

Однако! Магазин работает с 10 до 20 часов, исключая 20 часов. Обеденный перерыв длится с 13 до 14 часов, исключая 14 часов, а с 14 до 14:30 проходит совещание – исключая 14:30.

среда, 13 декабря 2023 г.

Имитация ассоциативных массивов в PL/pgSQL

В языке PL/pgSQL нет ассоциативных массивов, которые позволяют получить значение по ключу. И это досадно. Но ладно.

Первый способ имитировать ассоциативный массив

Создайте два массива, упорядоченных по одному и тому же критерию. Первый из них должен содержать ключи, второй - значения. После этого для получения значения по ключу нужно

  1. найти индекс элемента первого массива, содержащего значение ключа,
  2. по найденому индексу получить значение из второго массива.

пятница, 11 августа 2023 г.

Десять лет спустя, или Установка PostgreSQL на Windows

10 лет назад я написал первый пост в мой блог – про установку Oracle XE 11gR2 на Windows. Сколько воды утекло...

В 2022 комания Oracle удалила мой аккаунт, которым я пользовался лет двадцать, после того как Россия попала под экспортные ограничения. (Как в том анекдоте, где опытный кадровик помогает молодому коллеге справиться к горой резюме от кандидатов, которые тому нужно просмотреть. Половину резюме – сразу в мусорную корзину со словами "Лузеры нам не нужны!") Но жизнь продолжается.

четверг, 25 мая 2023 г.

Неизвестное vs Отсутствующее, или Двуликий NULL

Когда-то я уже писал о "многоликом NULL", см. Часть I и Часть II. Сегодняшний пост в дополнение и в развитие этой темы.

Я неоднократно встречал утверждение, что NULL в SQL нужно понимать как "неизвестно что". С этим согласуется поведение операторов сравнения при сравнении двух NULL (команды выполнены в PostgreSQL 15):

select 1
where null = null
   or null != null
   or null < null
   or null <= null
   or null >= null
   or null > null
;

no rows

понедельник, 24 апреля 2023 г.

dbang! Утилиты для работы с БД

Написанные на Python, утилиты dbang позволяют существенно сэкономить усилия при решении типичных задач, связанных с БД:

  • ddiff.py - выполняет запросы к двум БД и формирует отчет о расхождениях;
  • dtest.py - выполняет запросы к БД и формирует отчет о найденных проблемах;
  • dget.py - выгружает данные из БД в файлы csv, xlsx или html;
  • dput.py - загружает данные из файлов csv или xlsx в таблицы БД;
  • hedwig.py - на основе файлов создает и отправляет е-мейл.

Утилиты могут работать с СУБД Oracle, PostgreSQL, SQLite и MySQL.

воскресенье, 22 января 2023 г.

Кейс: изменение значения первичного ключа

Если значение первичного ключа изменяется не при выполнении специальных административных процедур, а в ходе обычной эксплуатации системы, то это выглядит как ошибка проектирования системы. Однако, иногда приходится иметь дело с такими системами.

Вопрос об изменении значения первичного ключа может также возникнуть в контексте интеграции систем.

Например, система А посылает в шину данных сообщения об изменениях бизнес-сущности Товар. И в этих сообщениях каждый отдельный экземпляр сущности – индивидуальный товар – идентифицируется бизнес-ключом, значение которого может быть изменено пользователем системы А (см. мой пост Кейс: изменение значения бизнес-ключа). А в системе Б, которая получает сообщения из шины данных и на их основании актуализирует собственную копию бизнес-сущности Товар, бизнес-ключ является первичным ключом таблицы в БД. И на него ссылаются внешние ключи из других таблиц.

Сможет ли система Б обновить первичный ключ, если она получит сообщение об изменении бизнес-ключа?

четверг, 26 мая 2022 г.

Периодические таблицы (не химия)

Время от времени приходится работать с таблицами БД, где записи имеют период действия, заданный датой начала и датой конца (последнего дня) периода. Это может быть таблица с ценами товаров, где в разные периоды времени цена одного и того же товара разная. Или таблица с конфигурационными параметрами, где значения параметров разные в разные периоды времени. При этом в каждую конкретную дату у товара может быть только одна действующая цена, а у конфигурационного параметра только одно значение параметра. То есть, периоды действия записей с одним и тем же товаром или параметром не должны пересекаться.

В связи с этим при вставке или изменении записи нужно проверять, не приведет ли эта операция к появлению в таблице записей с пересекающимися периодами.