Принципы движка хранения


1 Обзор MARS3

Движок хранения MARS3 использует гибридный метод хранения строк-столбцов для достижения высокой скорости записи данных и экстремальной степени сжатия.

MARS3 поддерживает обновление и удаление данных через ключевые слова UPDATE и DELETE (за исключением режима Unique).

MARS3 поддерживает добавление и удаление столбцов, а также операции COPY и pg_dump.

1.1 Внутренний механизм

Для каждой отдельной таблицы MARS3 внутреннее хранение использует структуру LSM-дерева (Log-Structured Merge Tree). LSM-дерево — это иерархическая, упорядоченная, ориентированная на диск структура данных. Её основной принцип заключается в максимальном использовании производительности диска для пакетных последовательных операций записи, что обеспечивает значительно более высокую производительность по сравнению со случайными записями.

Внутренняя архитектура MARS3 представлена ниже:

Мы проанализируем приведённую выше диаграмму по уровням в концептуальном виде.

1.1.1 Ключ сортировки

  • В MARS3 данные хранятся в упорядоченном виде. При создании таблицы необходимо указать порядок сортировки, задав один или несколько столбцов сортировки. Поля, участвующие в этом порядке сортировки, называются ключами сортировки.
  • Ключи сортировки можно задать только один раз и нельзя изменять, добавлять или удалять.
  • Для максимального использования преимуществ упорядочивания рекомендуется выбирать в качестве ключей сортировки поля, которые часто используются и обладают хорошими фильтрующими свойствами. Например, в таблице мониторинга устройств в качестве ключей сортировки могут использоваться временные метки событий и идентификаторы устройств.
  • Если ключ сортировки имеет текстовый тип и может быть отсортирован по байтовому порядку, использование COLLATE C для этого столбца ускорит сортировку.
  • Ключевое слово SQL для указания ключа сортировки: ORDER BY.

1.1.2 Хранение строк и столбцов

  • MARS3 поддерживает хранение данных в режиме сначала строки, затем столбцы, а также прямое хранение в столбцовом формате. Режим загрузки можно задать с помощью параметра prefer_load_mode. Подробности см. в разделе параметры конфигурации.
  • При использовании гибридной модели хранения данные сначала записываются в формате хранения строк, а затем преобразуются в столбцовый формат при достижении определённого объёма данных.
  • По сравнению с немедленным преобразованием данных в столбцовый формат, этот подход имеет следующие преимущества:
    • Более высокая скорость записи для частых, мелких пакетов данных
    • Отсутствие необходимости в большом объёме памяти для кэширования данных
    • Обеспечение равномерного количества кортежей в каждом блоке данных

1.1.3 Run, инкрементальные файлы и метаданные

  • На основе ключа сортировки данные в MARS3 хранятся в упорядоченном виде. Непрерывный сегмент упорядоченных данных называется Run.
  • Runs делятся на два типа. Для обеспечения высокой скорости записи вставляемые данные сохраняются в строковых Runs. Затем, для упрощения чтения и сжатия, строковые Runs преобразуются в столбцовые Runs.
  • Каждый Run имеет собственный инкрементальный файл. Помимо файла данных, содержащего основные данные, существуют также Toast-файлы для хранения больших блоков данных, Delta-файлы для хранения информации об удалениях, Index-файлы для хранения индексной информации и link-файлы для хранения информации о слиянии (см. следующий раздел «Слияние и сборка мусора») (инкрементальные файлы для строковых и столбцовых Runs немного различаются).
  • Кроме того, для отслеживания местоположения этих файлов мы записываем дополнительную информацию, известную как метаданные. Метаданные включают местоположение файла, его размер, количество строк данных, статус сжатия и другие детали.
  • Размер Run (настраивается параметром rowstore_size) можно гибко изменять для оптимизации производительности в различных сценариях.

1.1.4 Слияние и сборка мусора

  • Если существует перекрытие диапазонов данных в Run, это может вызвать усиление чтения и снизить эффективность запросов. Поэтому, когда количество Runs на диске превышает определённый порог, MARS3 выполняет слияние и сортировку нескольких Runs на диске, в результате чего формируется один Run. Этот процесс называется слиянием.
  • Во время слияния данные остаются доступными для чтения и записи:
    • При чтении данных читаются только входные файлы слияния
    • При записи данных процесс слияния не считывает новые записанные данные
    • Чтение, запись и слияние не блокируют друг друга
  • После завершения слияния Runs, участвовавшие в слиянии, автоматически определяют, когда они больше не нужны, на основе идентификатора транзакции, и помечаются как подлежащие сборке мусора.

1.1.5 Уровни

  • Для обеспечения того, чтобы входные файлы слияния имели схожий размер (чтобы избежать слияния чрезвычайно больших файлов с маленькими), Runs организованы в уровни, максимально 10 уровней: L0, L1, L2...L9.
  • Когда количество Runs на уровне достигает определённого порога, или общий размер нескольких Runs на одном уровне превышает порог, запускается слияние. После слияния в один Run он повышается на более высокий уровень. Кроме того, для ускорения повышения Runs внутри одного уровня могут выполняться несколько задач слияния одновременно.

1.1.6 MARS3 Brin-индекс

  • MARS3 поддерживает создание, удаление и добавление Brin-индексов.
  • Каждый Run создаёт собственный независимый файл Brin-индекса при его формировании.
  • Пример: CREATE INDEX brin_idx ON t1 USING mars3_brin(time,tag_id);

1.1.7 Сжатие

  • По умолчанию все столбцы данных в MARS3 сжимаются с использованием алгоритма lz4.
  • Поддерживается ручное указание цепочек алгоритмов кодирования и сжатия, которые могут быть заданы для всей таблицы или для отдельных столбцов.

1.1.8 Поддержка механизма MVCC

  • Механизм MVCC (Multiversion Concurrency Control) обычно называют управлением многими версиями. Его основная функция — обработка обновлений, изменений и удалений данных.
  • В управлении многими версиями обновления и удаления данных не обязательно выполняются над исходными данными. Вместо этого создаётся новая версия, исходные данные помечаются как недействительные, а новые данные добавляются в новую версию, в результате чего формируется несколько версий данных. Каждая запись связана с идентификатором версии, и все исторические версии сохраняются.
  • В MARS3 операции обновления и удаления не изменяют исходные данные на месте. Вместо этого они используют Delta-файлы и информацию о версиях для маскировки старых данных, тем самым контролируя видимость данных.
  • Примечание: Постоянное обновление или удаление данных из одного и того же Run приводит к непрерывному увеличению физического пространства, занимаемого Delta-файлами для этого Run. Однако, как только все данные из текущего Run будут удалены, объём пространства перестанет расти. Кроме того, операция слияния в MARS3 автоматически очищает Dead данные, хотя вы также можете запланировать регулярное использование VACUUM для очистки Dead данных.

1.1.9 Запись данных

  • Данные записываются в память через INSERT, затем записываются в Run уровня L0.
  • Размер Run в L0 настраивается. Подробности см. в разделе параметров конфигурации ниже.

1.1.10 Обновление и удаление

  • MARS3 использует DELETE для удаления. Удаления записываются в Delta-файл, соответствующий Run, а фактическое удаление данных происходит во время слияния Run.
  • MARS3 использует UPDATE для обновления. Обновление сначала удаляет исходные данные, а затем повторно вставляет новую запись.
  • Режим Unique в MARS3 в настоящее время не поддерживает удаление. Обновления не требуют явного указания ключевого слова UPDATE; достаточно выполнить команду INSERT, чтобы автоматически завершить операцию. Для обновления конкретной записи, связанной с уникальным ключом (то есть значением ключа, заданного при создании таблицы), просто вставьте новую запись с тем же уникальным ключом. Например, CREATE TABLE mars3_t(c1 int NOT NULL, c2 int) USING MARS3 WITH (uniquemode=true) ORDER BY (c1, c2);, где уникальный ключ — (c1, c2).

Примечания!
Если включен режим Unique, первое поле в предложении ORDER BY должно быть определено с ограничением NOT NULL.

1.2 Использование MARS3

1.2.1 Создание таблицы MARS3

Предположим, что расширение matrixts уже создано. Простейший способ создания таблицы — добавить предложение USING к оператору CREATE TABLE и добавить предложение ORDER BY. Дополнительные примеры см. в разделе Лучшие практики проектирования таблиц.

=# CREATE TABLE metrics (
    ts              timestamp,
    dev_id          bigint,
    power           float,
    speed           float,
    message         text
) USING MARS3 
  ORDER BY (dev_id,ts);

Примечания!
Таблица MARS3 поддерживает создание Brin-индексов, но это не обязательно; таблица MARS3 обязана использовать предложение ORDER BY для задания ключа сортировки.


1.2.2 Параметры конфигурации

Примечания!
Данные параметры конфигурации являются параметрами на уровне таблицы. Вы можете использовать конфигурацию через предложение WITH(mars3options='a=1,b=2,...') только при создании таблиц (за исключением параметра compress_threshold, который также поддерживается MARS2, и который можно настраивать только через предложение WITH). Подходит для отдельной таблицы и не может быть изменён после настройки. Подробнее см. Параметры конфигурации таблицы данных.

Следующие параметры используются для настройки размера Run уровня L0, а также косвенно влияют на размер Run выше уровня L1.

Параметр Единицы Значение по умолчанию Диапазон значений Описание
rowstore_size МБ 64 8 ~ 1024 Используется для управления переключением Run уровня L0. Когда объём данных превышает это значение, следующий Run переключается

Следующие параметры используются для установки порога сжатия, что позволяет настроить эффект сжатия и повысить эффективность чтения. Если порог сжатия установлен слишком низко, эффект сжатия может быть незначительным; если установлен слишком высоко, потребление памяти возрастает.

Параметр Единицы Значение по умолчанию Диапазон значений Описание
compress_threshold Кортежи 1200 1 ~ 100000 Порог сжатия. Используется для управления количеством кортежей (кортежей) в каждом столбце одной таблицы, сжимаемых за один раз, что является верхним пределом числа сжимаемых кортежей в одной единице

Следующие параметры используются для указания режима загрузки данных в MARS3.

Параметр Единицы Значение по умолчанию Диапазон значений Описание
prefer_load_mode normal normal / bulk Режим загрузки данных. normal обозначает нормальный режим. Новые данные сначала записываются в строковый Run уровня L0. После накопления в rowstore_size столбцовый Run переходит на уровень L1. По сравнению с режимом bulk, преобразование в столбцовый формат становится асинхронным, что подходит для сценариев с частыми мелкими пакетами записи при достаточной пропускной способности I/O и чувствительности к задержкам; bluk обозначает режим пакетной загрузки, подходящий для сценариев с редкими крупными пакетами записи, при котором данные напрямую записываются в столбцовый Run уровня L1. По сравнению с режимом normal, сокращается одна операция I/O. Преобразование в столбцовый формат становится синхронным, что подходит для сценариев с редкими крупными пакетами записи, при недостаточной пропускной способности I/O и низкой чувствительности к задержкам

Следующие параметры используются для указания коэффициента увеличения размера уровня.

| Параметр | Единицы | Значение по умолчанию | Диапазон значений | Описание | | -- | -- | -- | -- | -- | -- | -- | | level_size_amplifier | | 8 | 1 ~ 1000 | Коэффициент увеличения размера уровня. Порог для запуска операции слияния рассчитывается как: rowstore_size * (level_size_amplifier ^ level). Чем больше значение, тем медленнее скорость чтения и быстрее скорость записи. Конкретное значение можно определить на основе информации о конкретном сценарии (больше записей, меньше чтений, коэффициент сжатия и т.д.). Примечание: Убедитесь, что количество Run на уровне не превышает допустимое число, иначе это повлияет на производительность запросов и даже может препятствовать вставке новых данных |

Пример конфигурации:

=# CREATE TABLE metrics (
    ts              timestamp,
    dev_id          bigint,
    power           float,
    speed           float,
    message         text
) USING MARS3
WITH (compress_threshold=1200,mars3options='rowstore_size=64')
ORDER BY (dev_id,ts);

1.2.3 Функции инструментов

  • matrixts_internal.mars3_level_stats: Проверяет состояние каждого уровня MARS3-таблицы, позволяя оценить её состояние, например, выполнилось ли слияние Run, как ожидалось, соответствует ли их количество ожидаемому и т.д.;
  • matrixts_internal.mars3_files: Проверяет состояние файлов MARS3-таблицы, позволяя увидеть, соответствуют ли расширенные и инкрементальные файлы таблицы MARS3 (файлы данных, Delta-файлы, Index-файлы и т.д.) ожиданиям;
  • matrixts_internal.mars3_info_brin: Просматривает состояние Brin-индекса в MARS3-таблице.


2 Обзор MARS2

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

2.1 Внутренние принципы

Таблица MARS2 аналогична MARS3 и также использует структуру LSM-дерева и хранится. Внутренняя схема MARS2 представлена ниже: Мы интерпретируем приведённую выше диаграмму по уровням в концептуальном виде.

2.1.1 Ключ сортировки

  • В MARS2 данные хранятся в упорядоченном виде. При создании таблицы необходимо задать порядок сортировки путём создания индекса. Поля, участвующие в этом порядке сортировки, называются ключами сортировки.
  • Ключ сортировки можно задать только один раз, его нельзя изменять или удалять.
  • Для максимального повышения производительности, обеспечиваемого упорядочиванием, рекомендуется выбирать в качестве ключей сортировки поля, которые часто используются и обладают хорошими фильтрующими свойствами. Например, в таблице мониторинга устройств в качестве ключей сортировки могут использоваться временные метки событий и идентификаторы устройств.
  • Если ключ сортировки имеет текстовый тип и может быть отсортирован по байтовому порядку, то использование COLLATE C в этом столбце ускорит сортировку.

2.1.2 Выполнение и метаинформация

  • В соответствии с ключом сортировки данные, хранящиеся в MARS2, упорядочены, и непрерывный упорядоченный фрагмент данных называется Run.
  • Для возможности определения местоположения Run, записывается его расположение хранения — это называется метаинформацией Run.
  • Одновременно метаинформация также фиксирует минимальное и максимальное значения Run, что позволяет фильтровать данные при запросе.
  • При вставке данных данные сначала сортируются в памяти, поэтому размер Run зависит от объёма памяти, выделенной для сортировки.

2.1.3 Слияние

  • Если диапазоны данных в Run перекрываются, это приводит к усилению чтения и снижению эффективности запросов. Поэтому, когда количество Run на диске превышает определённое значение, MARS2 загружает несколько Run с диска в память, сортирует их и выводит в виде одного Run. Этот процесс называется слиянием.
  • Во время слияния данные остаются доступными для чтения и записи:
    • При чтении данных читаются только входные файлы слияния;
    • При записи данных процесс слияния не учитывает новые записанные данные;
    • Чтение, запись и слияние не блокируют друг друга.

2.1.4 Уровни

  • Для того чтобы входные файлы слияния имели сопоставимый размер (избегая слияния крупных файлов с мелкими), Run организованы в уровни: L0, L1, L2.
  • Когда размер данных после слияния превышает определённый порог, они повышаются на более высокий уровень. Процесс выглядит следующим образом:
      1. Новые вставленные данные находятся в L0. Когда количество Run достигает определённого числа (настраиваемое, см. параметр конфигурации mars2_automerge_threshold), запускается слияние L0, объединяющее все Run L0 в один Run.
      1. Если размер результирующего Run превышает 25 МБ (настраиваемый, см. параметр конфигурации level0_upgrade_size), он повышается до L1.
      1. Если суммарный размер Run в L1 превышает 1000 МБ (настраиваемый, см. level1_upgrade_size) после повышения до L1, запускается слияние, объединяющее все Run L1 в один Run.
      1. Если размер результирующего Run превышает 1000 МБ (настраиваемый, см. level1_upgrade_size), он повышается до L2.
      1. Run, достигшие уровня L2, больше не сливаются.

2.1.5 Колоночное хранение

  • MARS2 использует колоночный метод хранения данных. При доступе к диску необходимо считывать только те столбцы, которые используются в запросе, что снижает I/O.
  • Данные одного и того же столбца имеют одинаковый тип, что упрощает сжатие и экономит место на диске.
  • Кроме того, колоночное хранение хорошо подходит для векторизованного выполнения, что значительно ускоряет скорость выполнения запросов. Подробности см. в разделе Векторизованный движок выполнения.

2.1.6 Фильтрация MINMAX

  • Метаинформация Run, описанная выше, содержит минимальные и максимальные значения для фильтрации при запросах.
  • Поскольку фильтрация выполняется на основе метаинформации, сами данные не загружаются, что снижает нагрузку на I/O по сравнению с последовательным сканированием (сначала чтение данных, затем фильтрация) и позволяет выполнять фильтрацию быстрее.
  • При создании таблиц с использованием MARS2 минимальные и максимальные значения по умолчанию не записываются — их необходимо явно указать.

Сначала создайте расширение matrixts:

=# CREATE EXTENSION matrixts ;

Явное объявление записи минимальных и максимальных значений.

=# CREATE TABLE metrics (
    ts              timestamp   ENCODING(minmax),
    dev_id          bigint      ENCODING(minmax),
    power           float,
    speed           float,
    message         text
) USING MARS2;

Создание индекса mars2_btree.

=# CREATE INDEX ON metrics
USING mars2_btree (ts, dev_id);
  • Минимальные и максимальные значения могут быть определены как для ключей сортировки, так и для несортированных столбцов. Эффект более выражен при определении для ключа сортировки. В выражениях MINMAX может быть записан как в верхнем, так и в нижнем регистре.
  • Кроме того, MINMAX может быть определён для максимум 32 столбцов.

2.1.7 Btree-индекс MARS2

  • Помимо MINMAX, MARS2 имеет встроенный индекс (то есть индекс, создаваемый при создании таблицы).
  • В настоящее время можно определить только один индекс — то есть только один глобальный порядок сортировки.
  • В отличие от обычного Btree-индекса, Btree-индекс MARS2:
    • является разреженным, поэтому занимает меньше места;
    • поскольку данные сами по себе упорядочены, индексные сканирования не генерируют случайные I/O-операции.

2.1.8 Сжатие

То же, что и в MARS3.

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

2.1.9 Запись данных

  • Данные записываются в память через INSERT, после чего проходят через указанные процессы для формирования Run.
  • Если объём вставляемых данных велик и превышает объём памяти для сортировки, создаётся несколько Run.
  • Размер памяти для сортировки можно настроить — подробности см. в разделе «2.2.2 Параметры конфигурации».

2.1.10 Обновление и удаление

  • MARS2 в настоящее время не поддерживает обновление и удаление данных.
  • Операцию обновления можно заменить режимом Unique.
  • Операцию удаления можно выполнить только путём удаления или TRUNCATE партиционированной таблицы.

2.2 Использование MARS2

2.2.1 Создание таблицы MARS2

При условии, что расширение matrixts уже создано, простейший способ создания таблицы — добавить к оператору CREATE TABLE ключевое слово USING и создать индекс. Примеры расширенного использования см. в разделе Лучшие практики проектирования таблиц.

=# CREATE TABLE metrics (
    ts              timestamp,
    dev_id          bigint,
    power           float,
    speed           float,
    message         text
) USING MARS2;

=# CREATE INDEX ON metrics
USING mars2_btree (ts, dev_id);

2.2.2 Параметры конфигурации

Примечание!
Следующие параметры на уровне таблицы — это параметры, которые можно настраивать только с помощью ключевого слова WITH при создании таблицы. Они подходят для отдельных таблиц и не могут быть изменены после настройки. Глобальные параметры — это параметры, которые можно настраивать на уровне сессии или системы; для изменения на уровне системы необходимо выполнить mxstop -u. Подробнее см. Параметры конфигурации таблиц.

Следующие параметры управляют слияниями (Merge), и их влияние на слияния описано в разделе «Уровни» выше.

Параметры управления слиянием Единицы Значение по умолчанию Диапазон значений Описание
mars2_automerge_threshold run 32 10 - 2048 Управляет всеми таблицами MARS2: сколько Run должно накопиться в L0, чтобы запустить слияние. Это глобальный параметр. Для индивидуальной настройки для отдельной таблицы используйте параметр таблицы level0_merge_threshold.
level0_merge_threshold run 32 1 - 2048 Управляет количеством Run, при достижении которого запускается слияние. Это параметр на уровне таблицы.
level0_upgrade_size MB 25 1 - 10000 Управляет размером повышения уровня L0 → L1 для отдельной таблицы. Если результат слияния L0 превышает этот размер, он повышается до L1. Это параметр на уровне таблицы.
level1_upgrade_size MB 1000 1 - 10000 Управляет размером повышения уровня L1 → L2 для отдельной таблицы. Если результат слияния L1 превышает этот размер, он повышается до L2. Это параметр на уровне таблицы.
  • Если вставляется мало данных за раз (каждая вставка соответствует одному Run), слияние будет запускаться слишком часто, что неэффективно. В этом случае можно увеличить параметры mars2_automerge_threshold / level0_merge_threshold, чтобы увеличить количество входных Run в слияние и снизить частоту слияний.
  • Если результат слияния L0/L1 не достигает размера для повышения до следующего уровня, в следующем цикле слияние объединит его с новыми Run, что приведёт к усилению записи. Чтобы избежать этого, можно уменьшить level0_upgrade_size / level1_upgrade_size, чтобы данные быстрее переходили на следующий уровень.

Следующие параметры управляют сжатием и влияют на его эффективность. Если при слишком низких значениях эффект сжатия незаметен, а при слишком высоких — увеличивается потребление памяти.

Параметры управления сжатием Единицы Значение по умолчанию Диапазон значений Описание
compress_threshold Tuple 1200 1 - 100000 Порог сжатия. Управляет количеством кортежей (tuples), подлежащих сжатию в одной таблице. Это максимальное количество кортежей, сжимаемых в одном блоке. Это параметр на уровне таблицы.

Следующие параметры управляют памятью. Эти параметры определяют объём памяти для сортировки при вставке данных. При вставке в несколько партиций каждая партиция выделяет память, указанную в mars2_sort_mem_core; если её недостаточно, объём увеличивается, но общий объём не превышает mars2_sort_mem.

Параметры памяти для сортировки Единицы Значение по умолчанию Диапазон значений Описание
mars2_sort_mem KB 2097152KB (2 ГБ) 128KB - 2147483647KB (~2048 ГБ) Управляет объёмом памяти для сортировки при каждой отдельной вставке. Если целевая таблица является партиционированной, все партиции делят этот объём памяти. Это глобальный параметр.
mars2_sort_mem_core KB 16384KB (16 МБ) 128KB - 2147483647KB (~2048 ГБ) Управляет минимальным объёмом памяти, выделяемым для каждой отдельной партиции. Это глобальный параметр.

Примеры параметров на уровне таблицы:

=# CREATE TABLE metrics (
    ts              timestamp,
    dev_id          bigint,
    power           float,
    speed           float,
    message         text
) 
USING MARS2
WITH (compress_threshold=1200,level0_merge_threshold=32);

=# CREATE INDEX ON metrics
USING mars2_btree (ts, dev_id);

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

=# SET mars2_sort_mem TO 2097152;

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

=# gpconfig -c mars2_sort_mem -v 2097152
=# \q
$ mxstop -u


3 Обзор HEAP

HEAP — это стандартный движок хранения YMatrix, также известный как heap-хранилище, унаследованный от PostgreSQL. Поддерживает только строковое хранение, не поддерживает колоночное хранение и сжатие. Реализован на основе механизма MVCC и подходит для сценариев с большим количеством операций обновления и удаления.

3.1 Использование механизма MVCC

Под влиянием механизма MVCC таблица HEAP не удаляет данные физически при выполнении операций обновления и удаления, а лишь использует информацию о версиях данных для скрытия старых данных (контролирует их видимость). Поэтому при массовом обновлении или удалении данных физический объём, занимаемый таблицей HEAP, будет постоянно расти, и необходимо регулярно выполнять VACUUM для плановой очистки устаревших данных.

3.2 Использование HEAP

Таблицу HEAP в YMatrix можно создать с помощью следующего SQL-запроса:

=# CREATE TABLE disk_heap(
    time timestamp with time zone,
    tag_id int,
    read float,
    write float
)
DISTRIBUTED BY (tag_id);


4 Обзор AO

Таблицы с движками хранения AOCO и AORO объединяются под общим названием AO (Append-Optimized) — таблицы с оптимизацией на добавление. Они поддерживают операции вставки, обновления и удаления, а также сжатие. AORO поддерживает строковое хранение, AOCO — колоночное.

Логическая и физическая структура таблиц AO существенно отличается от структуры таблиц HEAP. Как упоминалось ранее, таблицы HEAP используют механизм MVCC для контроля видимости данных после обновлений и удалений, тогда как таблицы AO используют дополнительную битмап-таблицу, в которой указывается, какие данные в таблице AO являются видимыми.

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

Примечание!
Для подробной информации о движках хранения, их использовании и лучших практиках см. Лучшие практики проектирования таблиц.