BI Consult Desktop Logo BI Consult Mobile Logo
  • Russian BI Исследование российских bi
  • Перейти на Fine BI
  • Контакты
  • +7 812 334-08-01
    +7 499 608-13-06
  • Отправить сообщение
  • Главная
  • Продукты Эксперт-BI
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Сельское хозяйство
    • Энергетика
    • FMCG
    • Девелоперы
    • Маркетплейсы
    • Пищевая промышленность
    • Фармацевтика
    • Построение Data Platform
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и FP&A
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • IBP
    • ИТ (CIO)
    • Закупки
  • Платформы
    • Системы бизнес-анализа (BI)
    • Интегрированное бизнес-планирование (IBP)
    • Хранилища данных (DWH / Lakehouse)
    • Каталоги данных (Data Catalog)
    • Системы ETL и ELT
    • AI / Исскуственный интеллект
    • Шина данных (ESB)
    • Система управления мастер-данными (MDM)
    • Семантический слой
  • Услуги
    • Переход на отечественные BI и DWH системы
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений и DWH
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Курсы
    • Учебный курс Информационная грамотность (Data Literacy)
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Greenplum
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt (Data Build Tool)
  • Компания
    • Руководство
    • Новости
    • Клиенты
    • Карьера
    • Скачать
    • Контакты

BI

  • FineBI
  • FineReport
  • FineDataLink
  • FineChatBI (FineAI)
  • Коннекторы данных из 1С в BI
  • Airflow / Nifi
  • Visiology
  • PIX BI
  • Modus BI
  • Yandex.DataLens
  • Open-source BI: Superset/Metabase
  • Luxms BI
  • AW BI + Alpha BI
  • FlyBI + Форсайт. Аналитическая Платформа
  • Loginom
  • Триафлай
  • AI / Исскуственный интеллект
  • Optimacros
  • Навигатор BI
  • Семантический слой

СУБД

  • Arenadata
  • ClickHouse
  • Greenplum
  • Postgres Professional
  • TData

Другое

  • Построение Data Platform
    • Аналитическое хранилище данных
    • Data Lake и Data Engineering
    • Подробнее про Data Lake
    • Внедрение Lakehouse
      • Apache Doris
      • StarRocks
      • Trino
    • Миграция витрин из пропиетарных DWH на новый стек
    • Учебный курс "Современная архитектура хранилища данных"
Главная » Курсы по системам бизнес-анализа и методологии » Учебный курс по PostgreSQL » Как устроен PostgreSQL » Внутреннее устройство записи XLOG PostgreSQL

Внутреннее устройство записи XLOG PostgreSQL

Запись XLOG состоит из заголовка и каждой связанной с ним части данных. В первом подразделе описывается структура заголовка, остальные два подраздела посвящены описанию структуры порции данных в версиях 9.4 и более ранних версий, а также в версии 9.5 (в версии 9.5 формат данных изменился).

 

Заголовок записи XLOG

Все записи XLOG имеют общую заголовочную часть, определяемую структурой XLogRecord. Ниже показана структура версии 9.4 и более ранних версий, в версии 9.5 она была изменена.

typedef struct XLogRecord
{
   uint32          xl_tot_len;   /* total len of entire record */
   TransactionId   xl_xid;       /* xact id */
   uint32          xl_len;       /* total len of rmgr data. This variable was removed in ver.9.5. */
   uint8           xl_info;      /* flag bits, see below */
   RmgrId          xl_rmid;      /* resource manager for this record */
   /* 2 bytes of padding here, initialize to zero */
   XLogRecPtr      xl_prev;      /* ptr to previous record in log */
   pg_crc32        xl_crc;       /* CRC for this record */
} XLogRecord;

 

Примечание: Заголовок записи XLOG в версии 9.5 и новее

В версии 9.5 и новее переменная xl_len)была удалена из структуры XLogRecord для оптимизации формата записи XLOG, что уменьшило ее размер на несколько байт.

XLogRecord

typedef struct XLogRecord
{
        uint32          xl_tot_len;             /* total len of entire record */
        TransactionId      xl_xid;                           /* xact id */
        XLogRecPtr      xl_prev;                /* ptr to previous record in log */
        uint8           xl_info;                /* flag bits, see below */
        RmgrId          xl_rmid;                /* resource manager for this record */
        /* 2 bytes of padding here, initialize to zero */
        pg_crc32c       xl_crc;                 /* CRC for this record */
        /* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */
} XLogRecord;

Помимо двух переменных, о которых речь пойдет ниже, большинство переменных настолько очевидны, что не нуждаются в отдельном описании.

И xl_rmid, и xl_info - это переменные, связанные с менеджерами ресурсов, которые представляют собой коллекции операций, связанных с функцией WAL, таких как запись и воспроизведение записей XLOG. Количество менеджеров ресурсов увеличивается с каждой версией PostgreSQL. Версия 10 содержит следующие менеджеры ресурсов:

Операция

Менеджер ресурсов

Операции с котежами

RM_HEAP, RM_HEAP2

Операции с индексами

RM_BTREE, RM_HASH, RM_GIN, RM_GIST, RM_SPGIST, RM_BRIN

Последовательные опеации

RM_SEQ

Операции с транзакциями

RM_XACT, RM_MULTIXACT, RM_CLOG, RM_XLOG, RM_COMMIT_TS

Опеации с табличным пространством

RM_SMGR, RM_DBASE, RM_TBLSPC, RM_RELMAP

Репликация

RM_STANDBY, RM_REPLORIGIN, RM_GENERIC_ID, RM_LOGICALMSG_ID

 

Вот несколько примеров того, как работают менеджеры ресурсов:

  • При выполении оператора  INSERT переменные заголовка xl_rmid и xl_info XLOG-записи устанавливаются в значения 'RM_HEAP' и 'XLOG_HEAP_INSERT' соответственно. При восстановлении кластера баз данных функция RM_HEAP heap_xlog_insert() выбирается в соответствии с xl_info и воспроизводит эту запись XLOG;
  • Аналогично, для оператора UPDATE переменная заголовка xl_info записи XLOG устанавливается в значение 'XLOG_HEAP_UPDATE', функция RM_HEAP heap_xlog_update() воспроизводит запись при восстановлении базы данных;
  • Когда транзакция фиксируется, переменные заголовка xl_rmid и xl_info записи XLOG устанавливаются в значения 'RM_XACT' и 'XLOG_XACT_COMMIT' соответственно. При восстановлении кластера базы данных функция xact_redo_commit() воспроизводит эту запись.

 

Примечание:

Структура XLogRecord в версии 9.4 и более ранних версиях определена в src/include/access/xlog.h , в версиях и новее - в src/include/access/xlogrecord.h.

Функции heap_xlog_insert и heap_xlog_update определены в src/backend/access/heap/heapam.c, а функция xact_redo_commit определена в src/backend/access/transam/xact.c.

 

Часть данных в рамках записи XLOG (версия 9.4 и более ранние версии)

Часть данных в записи XLOG можно разделить на резервный блок (содержащий всю страницу) и нерезервный блок (содержащий данные в зависимости от выполняемой операции).

Составляющие записи XLOG описаны ниже.

9.4.2.1. Резервный блок

Резервный блок состоит из двух структур данных и одного объекта данных:

  • Структура XLogRecord (заголовок);
  • Структура BkpBlock;
  • Целая страница за исключением свободного пространства.

 

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

BkpBlock

typedef struct BkpBlock @ include/access/xlog_internal.h
{
  RelFileNode node;        /* relation containing block */
  ForkNumber  fork;        /* fork within the relation */
  BlockNumber block;       /* block number */
  uint16      hole_offset; /* number of bytes before "hole" */
  uint16      hole_length; /* number of bytes in "hole" */
 
  /* ACTUAL BLOCK DATA FOLLOWS AT END OF STRUCT */
} BkpBlock;

 

Нерезервный  блок

В нерезервных блоках расположение частей данных отличается в зависимости от операции. Здесь в качестве показательного примера приводится запись XLOG для оператора INSERT. В этом случае запись XLOG состоит из двух структур данных и одного объекта данных:

  • Структура XLogRecord
  • Структура xl_heap_insert 
  • Вставленный кортеж, некотрое количество байтов которого удалено.

 

Структура xl_heap_insert содержит переменные, идентифицирующие вставленный кортеж в кластере базы данных (т.е. relfilenode таблицы, содержащей этот кортеж, и tid кортежа), а также флаг видимости данного кортежа.

xl_heap_insert 

typedef struct BlockIdData
{
   uint16          bi_hi;
   uint16          bi_lo;
} BlockIdData;
 
typedef uint16 OffsetNumber;
 
typedef struct ItemPointerData
{
   BlockIdData     ip_blkid;
   OffsetNumber    ip_posid;
}
 
typedef struct RelFileNode
{
   Oid             spcNode;             /* tablespace */
   Oid             dbNode;              /* database */
   Oid             relNode;             /* relation */
} RelFileNode;
 
typedef struct xl_heaptid
{
   RelFileNode     node;
   ItemPointerData tid;                 /* changed tuple id */
} xl_heaptid;
 
typedef struct xl_heap_insert
{
   xl_heaptid      target;              /* inserted tuple id */
   bool            all_visible_cleared; /* PD_ALL_VISIBLE was cleared */
} xl_heap_insert;

 

Примечание:

Причина удаления нескольких байт из вставленного кортежа описана в комментарии к исходному коду структуры xl_heap_header:

Мы не храним в WAL HeapTupleHeaderData вставленного или обновленного кортежа; мы можем сэкономить несколько байт, реконструировав поля, которые доступны в других местах записи WAL, или, возможно, просто не нуждаются в реконструировании.

 

Примечание:

Структура xl_heap_header определена в  src/include/access/htup.h, а структура CheckPoint - в src/include/catalog/pg_control.h.

 

Данные записи XLOG (версия 9.5 и новее)

В версии 9.4 и более ранних версиях не существовало общего формата записей XLOG, поэтому менеджер ресурсов должен был определять свой собственный формат. Это в большой степени усложняло реализацию функций, связанных с WAL. Чтобы решить эту проблему, в версии 9.5 повился общий структурированный формат, не зависящий от менеджеров ресурсов.

Данные в записи XLOG можно разделить на две части: заголовок и данные.

Заголовок содержит ноль или более XLogRecordBlockHeader, а также ноль или один XLogRecordDataHeaderShort (или XLogRecordDataHeaderLong). Он должен содержать хотя бы один из этих компонентов.

Если запись хранит полностраничное изображение (т. е. резервный блок), XLogRecordBlockHeader включает XLogRecordBlockImageHeader либо XLogRecordBlockCompressHeader, если блок сжат.

XLogRecordBlockHeader

/*
* Header info for block data appended to an XLOG record.
*
* 'data_length' is the length of the rmgr-specific payload data associated
* with this block. It does not include the possible full page image, nor
* XLogRecordBlockHeader struct itself.
*
* Note that we don't attempt to align the XLogRecordBlockHeader struct!
* So, the struct must be copied to aligned local storage before use.
*/
typedef struct XLogRecordBlockHeader
{
                    uint8                               id;                                                                             /* block reference ID */
                    uint8                               fork_flags;                     /* fork within the relation, and flags */
                    uint16                             data_length;                  /* number of payload bytes (not including page
                                                                                                                                                                  * image) */
 
                    /* If BKPBLOCK_HAS_IMAGE, an XLogRecordBlockImageHeader struct follows */
                    /* If BKPBLOCK_SAME_REL is not set, a RelFileLocator follows */
                    /* BlockNumber follows */
} XLogRecordBlockHeader;
 
/*
* The fork number fits in the lower 4 bits in the fork_flags field. The upper
* bits are used for flags.
*/
#define BKPBLOCK_FORK_MASK                0x0F
#define BKPBLOCK_FLAG_MASK                0xF0
#define BKPBLOCK_HAS_IMAGE                0x10           /* block data is an XLogRecordBlockImage */
#define BKPBLOCK_HAS_DATA                   0x20
#define BKPBLOCK_WILL_INIT                   0x40           /* redo will re-init the page */
#define BKPBLOCK_SAME_REL                   0x80           /* RelFileLocator omitted, same as
                                                                                                                                                                                       * previous */

 

XLogRecordBlockImageHeader

/*
* Additional header information when a full-page image is included
* (i.e. when BKPBLOCK_HAS_IMAGE is set).
*
* The XLOG code is aware that PG data pages usually contain an unused "hole"
* in the middle, which contains only zero bytes.  Since we know that the
* "hole" is all zeros, we remove it from the stored data (and it's not counted
* in the XLOG record's CRC, either).  Hence, the amount of block data actually
* present is (BLCKSZ - <length of "hole" bytes>).
*
* Additionally, when wal_compression is enabled, we will try to compress full
* page images using one of the supported algorithms, after removing the
* "hole". This can reduce the WAL volume, but at some extra cost of CPU spent
* on the compression during WAL logging. In this case, since the "hole"
* length cannot be calculated by subtracting the number of page image bytes
* from BLCKSZ, basically it needs to be stored as an extra information.
* But when no "hole" exists, we can assume that the "hole" length is zero
* and no such an extra information needs to be stored. Note that
* the original version of page image is stored in WAL instead of the
* compressed one if the number of bytes saved by compression is less than
* the length of extra information. Hence, when a page image is successfully
* compressed, the amount of block data actually present is less than
* BLCKSZ - the length of "hole" bytes - the length of extra information.
*/

typedef struct XLogRecordBlockImageHeader
{
                    uint16                             length;                                                 /* number of page image bytes */
                    uint16                             hole_offset;                   /* number of bytes before "hole" */
                    uint8                               bimg_info;                     /* flag bits, see below */
                     /*
                    * If BKPIMAGE_HAS_HOLE and BKPIMAGE_COMPRESSED(), an
                    * XLogRecordBlockCompressHeader struct follows.
                    */
} XLogRecordBlockImageHeader;
 
/* Information stored in bimg_info */
#define BKPIMAGE_HAS_HOLE                                        0x01           /* page image has "hole" */
#define BKPIMAGE_APPLY                                                 0x02           /* page image should be restored
                                                                                                                                                                                                            * during replay */
/* compression methods supported */
#define BKPIMAGE_COMPRESS_PGLZ      0x04
#define BKPIMAGE_COMPRESS_LZ4         0x08
#define BKPIMAGE_COMPRESS_ZSTD      0x10
 
#define       BKPIMAGE_COMPRESSED(info) \
                    ((info & (BKPIMAGE_COMPRESS_PGLZ | BKPIMAGE_COMPRESS_LZ4 | \
                                                               BKPIMAGE_COMPRESS_ZSTD)) != 0)

 

XLogRecordBlockCompressHeader

/*
* Extra header information used when page image has "hole" and
* is compressed.
*/
typedef struct XLogRecordBlockCompressHeader
{
                    uint16                             hole_length;                  /* number of bytes in "hole" */
} XLogRecordBlockCompressHeader;

 

XLogRecordDataHeader

/*
* XLogRecordDataHeaderShort/Long are used for the "main data" portion of
* the record. If the length of the data is less than 256 bytes, the short
* form is used, with a single byte to hold the length. Otherwise the long
* form is used.
*
* (These structs are currently not used in the code, they are here just for
* documentation purposes).
*/

typedef struct XLogRecordDataHeaderShort
{
                    uint8                               id;                                                                             /* XLR_BLOCK_ID_DATA_SHORT */
                    uint8                               data_length;                  /* number of payload bytes */
}                                                           XLogRecordDataHeaderShort;
 
#define SizeOfXLogRecordDataHeaderShort (sizeof(uint8) * 2)
 
typedef struct XLogRecordDataHeaderLong
{
                    uint8                               id;                                                                             /* XLR_BLOCK_ID_DATA_LONG */
                    /* followed by uint32 data_length, unaligned */
}                                                           XLogRecordDataHeaderLong;
 
#define SizeOfXLogRecordDataHeaderLong (sizeof(uint8) + sizeof(uint32))

 

Примечание: функция сжатия WAL

Функция сжатия WAL внутри PostgreSQL срабатывает (если мы включим ее) при записи полных страниц в WAL, что может сэкономить много накладных расходов на ввод-вывод. Уменьшенный размер сегмента WAL дает дополнительные преимущества при репликации и резервном копировании, поскольку необходимо передавать меньше данных.

В версии 9.5 и новее полностраничные изображения в записях XLOG можно сжимать с помощью метода сжатия LZ, задав параметр wal_compression = enable. В этом случае будет добавлена структура XLogRecordBlockCompressHeader.

Наглядные примеры приведены чуть ниже, как и в предыдущем подразделе.9.4.3.1.

 

 

Резервный блок

Резервный блок, созданный оператором INSERT, показан на рис. 106a. Он состоит из четырех структур данных и одного объекта данных:

  1. Структура the XLogRecord (заголовок);
  2. Структура XLogRecordBlockHeader, включающая в себя одну структуру LogRecordBlockImageHeader;
  3. Структура XLogRecordDataHeaderShort;
  4. Резевный блок;
  5. Структура the xl_heap_insert.

 

Структура XLogRecordBlockHeader содержит переменные, необходимые для идентификации блока в кластере базы данных (relfilenode, номер форка и номер блока). Структура XLogRecordImageHeader содержит длину этого блока и номер смещения. (Эти две структуры заголовков вместе могут хранить те же данные, что и структура BkBlock, использовавшаяся до вплоть доверсии 9.4).

В структуре XLogRecordDataHeaderShort хранится длина структуры xl_heap_insert, которая является основными данными записи.

 

Примечение: основные данные записи XLOG

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

Основные данные записей резервных блоков зависят от операторов, которые их создают. Например, оператор UPDATE добавляет xl_heap_lock или xl_heap_updated.

 

Нерезервный блок

Далее мы поговорим о нерезервном блоке, созданном оператором INSERT (см. рис. 106b). Он состоит из четырех структур данных и одного объекта данных:

  1. Структура XLogRecord (заголовок);
  2. Структура XLogRecordBlockHeader;
  3. Структура XLogRecordDataHeaderShort;
  4. Вставленный кортеж (точнее структура xl_heap_header);
  5. Структура xl_heap_insert  (основные данные).

 

Структура XLogRecordBlockHeader содержит три значения (relfilenode, номер форка и номер блока), указывающие на блок, в который был вставлен кортеж, а также длину части данных вставленного кортежа. Структура XLogRecordDataHeaderShort содержит длину новой структуры xl_heap_insert.

Новая структура xl_heap_insert содержит только два значения: номер смещения этого кортежа в блоке и флаг видимости. В структуре XLogRecordBlockHeader хранится большая часть данных, которые содержались в старой структуре xl_heap_insert.

xl_heap_insert

typedef struct xl_heap_insert
{
        OffsetNumber      offnum;            /* inserted tuple's offset */
        uint8           flags;
 
        /* xl_heap_header & TUPLE DATA in backup block 0 */
} xl_heap_insert;

 

В качестве последнего примера на рис. 106c отображена запись контрольной точки, состоящая из трех структур данных:

  1. Структура XLogRecord (заголовок);
  2. Структура XLogRecordDataHeaderShort;
  3. Структура CheckPoint (основные данные).

 

Примечание:

Структура xl_heap_header определена в src/include/access/htup.h, а структура CheckPoint - в src/include/catalog/pg_control.h.

Хотя новый формат кажется немного сложным, на самом деле, он достаточно хорошо проработаг. Кроме того, размер многих типов записей XLOG обычно меньше, чем у предыдущих. Размер новой контрольной точки больше, чем предыдущей, она содержит больше переменных.

 

Узнать стоимость решенияЗапросить видео презентацию

← Предыдущая статья
Внутреннее устройство сегмента WAL PostgreSQL
Следующая статья →
Создание записей XLOG в PostgreSQL
Запросить видео презентацию Запросить доступ к демо стенду online Узнать стоимость лицензий

Задать вопрос

loading...

Решения

Анализировать ФинансыУвеличивайте ПродажиОптимальный Склад и ЛогистикаМаркетинговые Метрики

Клиенты
  • «Лента» – первая по величине сеть гипермаркетов и четвертая среди крупнейших розничных сетей страны. Компания была основана в 1993 г. в Санкт-Петербурге.

    «Лента» управляет 249 гипермаркетами в 88 городах России и 131 супермаркетом в Москве, Санкт-Петербурге, Сибири, Уральском и Центральном регионах с общей торговой площадью около 1 494 тыс. кв. м. Средняя торговая площадь одного гипермаркета «Лента» составляет около 5 500 кв.м, средняя площадь супермаркета – 800 кв.м. Компания оперирует двенадцатью распределительными центрами. Штат компании – около 50, 5 тыс. человек.

  • Группа компаний "Дёке" производит товары для внешней отделки загородных домов. Ассортимент включает виниловый сайдинг, фасадные панели, водосточные системы, чердачные лестницы и гибкую битумную черепицу. Продукция Дёке вызывает гордость у сотрудников и партнеров компании.

  • ООО "Уральская транспортная компания" — это транспортно-логистическая компания, специализирующаяся на железнодорожных перевозках грузов, создана в 2009 году.

  • "Уральский банк реконструкции и развития" входит в топ-25 крупнейших банков России и список значимых кредитных организаций на рынке платежных услуг по версии ЦБ РФ.

  • Решения
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Энергетика
    • Фармацевтика
  • Услуги
    • Переход на отечественные BI и DWH
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Техническая поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Платформы
    • FineBI
    • FineReport
    • FineDataLink
    • Коннекторы данных из 1С в BI
    • Airflow + NiFi
    • Visiology
    • Luxms BI
    • Modus BI
    • PIX BI
    • Arenadata
    • ClickHouse
    • Greenplum
    • Postgres Professional
    • Open-source BI: Superset/Metabase
    • Loginom
    • Yandex.DataLens
    • AI / Исскуственный интеллект
    • Optimacros
    • Шины данных
  • Курсы
    • Учебный курс Информационная грамотность
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt
  • Функциональные решения
    • Создание Data Lake
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и прогнозная аналитика
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • Сквозная аналитика
  • Компания
    • О нас
    • Руководство
    • Новости
    • Клиенты
    • Скачать
    • Контакты
    • Политика конфиденциальности
RutubeVkontakteLinkedInYouTube
ООО "Би Ай Консалт",
ИНН: 7811437757,
ОГРН: 1097847154184
199178, Россия,
Санкт-Петербург,
6-ая линия В.О., Д. 63, 4 этаж
Тел: +7 (812) 334-08-01
Тел: +7 (499) 608-13-06
E-mail: info@biconsult.ru

 

 

 

 

 

×

Пользуясь сайтом, вы соглашаетесь с использованием cookies и политикой конфиденциальности.