
⚡Postgres и oversized-атрибуты
В Postgres страница — это базовая единица ввода-вывода данных, хранимых на диске (нельзя прочитать с диска меньше чем одну страницу). По умолчанию размер страницы составляет 8кб
Также Postgres не позволяет хранить одну запись на нескольких страницах. Однако, как известно существует множество типов данных, значения которых могут превышать 8кб (например, varchar). Возникает вопрос — как их уместить в одну страницу
TOAST (The Oversized-Attribute Storage Technique) — техника, когда мы храним значение аттрибута не напрямую в странице рядом с остальными аттрибутами, а перемещаем значения в отдельную toast-таблицу. В основной таблице храним указатель на запись в toast-таблице. Все это скрыто от пользователя, что позволяет не задумываясь хранить большие тексты/жсоны прямо в реляционной таблице (не делайте так), но в то же время имеет несколько неочевидных недостатков:
1. Идентификатор записи в toast-таблице имеет тип oid, который имеет 2^32 уникальных значений, что не так много. В случае когда все идентификаторы “потратятся”, и захочется сделать insert в основную таблицу, подразумевающий вставку в toast, то вставка не сработает
2. На toast-таблицу по-прежнему распространяются правила MVCC — если поредактировать колонку в основной таблице, значение которой лежит в toast, то старое значение в toast-таблице не удалится, а просто пометится удаленным. Физическое удаление и освобождение памяти произойдет после vacuum. Это может приводить к раздуванию toast-таблицы
—
Поэтому если у вас есть потребность хранить большие тексты/жсоны, и у сервиса высокая нагрузка/большой поток данных, то имеет смысл воспользоваться специализированными инструментами. Например, S3 — сам документ храним в S3, а в реляционной таблице храним просто s3_object_id. Получается тоже своего рода TOAST, но без вышеприведенных недостатков
Ставьте 👍 на этот пост, если нужен рассказ про S3
В Postgres страница — это базовая единица ввода-вывода данных, хранимых на диске (нельзя прочитать с диска меньше чем одну страницу). По умолчанию размер страницы составляет 8кб
Также Postgres не позволяет хранить одну запись на нескольких страницах. Однако, как известно существует множество типов данных, значения которых могут превышать 8кб (например, varchar). Возникает вопрос — как их уместить в одну страницу
TOAST (The Oversized-Attribute Storage Technique) — техника, когда мы храним значение аттрибута не напрямую в странице рядом с остальными аттрибутами, а перемещаем значения в отдельную toast-таблицу. В основной таблице храним указатель на запись в toast-таблице. Все это скрыто от пользователя, что позволяет не задумываясь хранить большие тексты/жсоны прямо в реляционной таблице (не делайте так), но в то же время имеет несколько неочевидных недостатков:
1. Идентификатор записи в toast-таблице имеет тип oid, который имеет 2^32 уникальных значений, что не так много. В случае когда все идентификаторы “потратятся”, и захочется сделать insert в основную таблицу, подразумевающий вставку в toast, то вставка не сработает
2. На toast-таблицу по-прежнему распространяются правила MVCC — если поредактировать колонку в основной таблице, значение которой лежит в toast, то старое значение в toast-таблице не удалится, а просто пометится удаленным. Физическое удаление и освобождение памяти произойдет после vacuum. Это может приводить к раздуванию toast-таблицы
—
Поэтому если у вас есть потребность хранить большие тексты/жсоны, и у сервиса высокая нагрузка/большой поток данных, то имеет смысл воспользоваться специализированными инструментами. Например, S3 — сам документ храним в S3, а в реляционной таблице храним просто s3_object_id. Получается тоже своего рода TOAST, но без вышеприведенных недостатков
Ставьте 👍 на этот пост, если нужен рассказ про S3