Техника TOAST ( PostgreSQL)

Материал из Циклопедии
Перейти к навигации Перейти к поиску

Техника TOAST (The Oversized-Attribute Storage Technique) (Методика хранения сверхбольших атрибутов) — используется для хранения больших по размеру данных в PostgreSQL. PostgreSQL использует программно определенный размер страницы (обычно 8 кБ) и не допускает, чтобы кортежи охватывали более одной страницы. Поэтому невозможно хранить очень большие значения полей напрямую. Чтобы обойти данное ограничение, большие значения полей сжимаются, разбиваются на несколько физических строк. Такая техника известна как TOAST.

Суть[править]

TOAST поддерживают только некоторые типы данных. Сделано это по причине того что нет необходимости задействовать лишние «расходы» на типы данных, которые не могут создавать большие значения полей. Такой тип данных должен иметь представление переменной длины (varlena), в котором первое 32-разрядное слово любого сохраненного значения содержит общую длину значения в байтах. Данная техника не ограничивает остальную часть представления. Все функции уровня C, поддерживающие такой тип данных, должны быть осторожны, чтобы обрабатывать входные значения TOASTed. (Обычно это делается путем вызова PG_DETOAST_DATUM, прежде чем делать что-либо с входным значением).

TOAST резервирует два бита varlena-слова: старшие биты для машин с обратным порядок байтов (big-endian) и младшие биты для машин с прямым порядком байтов (little-endian).
Возможны две комбинации:

  1. Самый старший/младший бит varlena-слова установлен, смежный бит сброшен. Это указывает на то, что данное значение имеет 1-байтовое, а не 4-байтовое, varlena-слова, а оставшиеся биты этого слова дают общий размер значения (включая байт длины) в байтах. Если остальные биты varlena-слова равны нулю, то данное значение является указателем на данные, хранящиеся в отдельной TOAST-таблице. При этом размер TOAST -указателя дает второй байт значения. Данные с однобайтовыми заголовками не выравниваются по какой-либо конкретной границе.
  2. Самый старший/младший бит varlena-слова сброшен, смежный бит установлен. Это говорит о том, что значение было сжато и должно быть распаковано перед использованием. В этом случае оставшиеся биты длины слова дают общий размер сжатых данных, а не исходных данных Сжатие также возможно и для значений, хранящихся в TOAST-таблицах (информацию об этом содержит TOAST-указатель).

Вы можете просмотреть текущие параметры TOAST для таблицы, открыв psql и выполнив:

\d+ table_name

Отдельное размещение TOAST на диске[править]

Размещаемые на диске TOAST-значения содержатся в таблице TOAST.[1] Отделённые значения делятся на порции (после сжатия, если оно применяется) размером не более TOAST_MAX_CHUNK_SIZE байт (по умолчанию это значение выбирается таким образом, чтобы на странице помещались четыре строки порций, то есть размер одной составляет порядка 2000 байт). Каждая порция хранится как отдельная строка в таблице TOAST, принадлежащей исходной таблице-владельцу. Каждая таблица TOAST имеет столбцы chunk_id (OID, идентифицирующий конкретное TOAST-значение), chunk_seq (последовательный номер для порции внутри значения) и chunk_data (фактические данные порции). Уникальный индекс по chunk_id и chunk_seq обеспечивает быструю выдачу значений. Таким образом, в указателе, представляющем отдельно размещаемое на диске значение TOAST, должно храниться OID таблицы TOAST, к которой нужно обращаться, и OID определённого значения (его chunk_id). Для удобства в данных указателя также хранится логический размер элемента данных (исходных данных без сжатия) и фактический размер хранимых данных (отличающийся, если было применено сжатие). Код обработки TOAST срабатывает, только когда значение строки, которое должно храниться в таблице, по размеру больше, чем TOAST_TUPLE_THRESHOLD байт (обычно это 2 Кб). Код TOAST будет сжимать и/или выносить значения поля за пределы таблицы до тех пор, пока значение строки не станет меньше TOAST_TUPLE_TARGET байт (также обычно 2 Кб) или уменьшить объём станет невозможно.
Код обработки TOAST распознаёт четыре различные стратегии хранения столбцов, совместимых с TOAST, на диске:

  • PLAIN не допускает ни сжатие, ни отдельное хранение; кроме того, отключается использование однобайтовых заголовков для типов varlena. Это единственно возможная стратегия для столбцов типов данных, которые несовместимы с TOAST.
  • EXTENDED допускает как сжатие, так и отдельное хранение. Это стандартный вариант для большинства типов данных, совместимых с TOAST. Сначала происходит попытка выполнить сжатие, затем — сохранение вне таблицы, если строка всё ещё слишком велика.
  • EXTERNAL допускает отдельное хранение, но не сжатие. Использование EXTERNAL ускорит операции над частями строк в больших столбцах text и bytea (ценой увеличения объёма памяти для хранения), так как эти операции оптимизированы для извлечения только требуемых частей отделённого значения, когда оно не сжато.
  • MAIN допускает сжатие, но не отдельное хранение. (Фактически, отдельное хранение, тем не менее, будет выполнено для таких столбцов, но лишь как крайняя мера, когда нет другого способа уменьшить строку так, чтобы она помещалась на странице.)

Эта схема имеет ряд преимуществ по сравнению с более простым подходом, когда значения строк могут занимать несколько страниц. Если предположить, что обычно запросы характеризуются выполнением сравнения с относительно маленькими значениями ключа, большая часть работы будет выполняться с использованием главной записи строки. Большие значения атрибутов в формате TOAST будут просто передаваться (если будут выбраны) в тот момент, когда результирующий набор отправляется клиенту. Таким образом, главная таблица получается гораздо меньше, и в общий кеш буферов помещается больше её строк, чем их было бы без использования отдельного хранения. Время обработки не отличалось от времени, необходимого для обработки таблицы без использования TOAST, в которой размер всех HTML-страниц был уменьшен до 7 Кб, чтобы они уместились в строках.

Отдельное размещение TOAST в памяти[править]

Указатели TOAST могут указывать на данные, размещённые не на диске, а где-либо в памяти текущего серверного процесса. Очевидно, что такие указатель не могут быть долговременными, но они, тем не менее, полезны.
В настоящее время поддерживаются два подварианта:

  • косвенные указатели на данные
  • указатели на развёрнутые данные.

Для всех типов указателей TOAST на данные в памяти, код обработки TOAST гарантирует, что такие данные не окажутся случайно сохранены на диске. Указатели TOAST в памяти автоматически сворачиваются в обычные значения varlena перед сохранением — а затем могут преобразоваться в указатели TOAST на диске, если без этого не смогут уместиться в содержащем их кортеже.

Указатель на развёрнутые данные[править]

Указатели на развёрнутые данные TOAST полезны для сложных типов, представление которых на диске плохо приспособлено для вычислительных целей. Указатели TOAST на развёрнутые значения далее подразделяются на:

  • указатели для чтения/записи
  • указатели только для чтения.

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

Косвенный указатель[править]

Косвенный указатель TOAST просто указывает на значение varlena, хранящееся где-то в памяти. Этот вариант изначально был реализован просто как подтверждение концепции, но в настоящее время он применяется при логическом декодировании, чтобы не приходилось создавать физические кортежи больше одного 1 ГБ (что может потребоваться при консолидации всех отделённых значений полей в одном кортеже). Данный вариант имеет ограниченное применение, так как создатель такого указателя должен полностью понимать, что целевые данные будут существовать, только пока существует указатель, и никакой инфраструктуры для сохранения их нет.

Источники[править]

  1. (Подробнее описано ниже)

Литература[править]

  • Информационные системы и базы данных: организация и проектирование -Пирогов Владислав Юрьевич-2009
  • Scalable Fuzzy Algorithms for Data Management and Analysis: Methods and Design -Laurent, Anne −2009
  • Heroku: Up and Running: Effortless Application Deployment and Scaling -Neil Middleton, Richard Schneeman- 2013