Что такое TOAST в PostgreSQL и зачем он нужен
Что проверяют
Знает ли Java-разработчик, что происходит в базе под его сущностями, когда в таблице есть текстовое, jsonb или бинарное поле на мегабайты. Вопрос почти всегда ведёт к следующему: почему выборка вроде бы простых строк вдруг стала дорогой.
Как отвечать
Строка в PostgreSQL не может пересекать границу страницы в восемь килобайт. Когда строка перестаёт помещаться в отведённый порог (примерно четверть страницы), включается TOAST: значения переменной длины сначала сжимаются, а если строка всё ещё велика, самые крупные из них выносятся в служебную таблицу, где хранятся кусками, а в основной строке остаётся ссылка. Для SQL всё это прозрачно, вручную ничего включать не нужно.
Полезно назвать стратегии хранения колонки: PLAIN запрещает вынос, MAIN старается сжать и оставить на месте, EXTERNAL выносит без сжатия, EXTENDED по умолчанию сжимает и выносит. EXTERNAL имеет смысл, когда к полю часто применяют substring: несжатое значение читается кусками, а не разжимается целиком.
Зачем это нужно: узкая основная строка значит больше строк на странице, меньше чтений и эффективнее кэш для запросов, которые большое поле не трогают. Обратная сторона в том, что обращение к вынесенному значению стоит дополнительных чтений и разжатия.
Практический вывод для кода: не тянуть большое поле жадной загрузкой сущности, брать проекции с явным списком колонок, а индексировать не сам текст, а выражение или хеш, потому что обычный индекс не примет слишком длинный ключ.
Где спотыкаются
Говорят, что порог применяется к отдельной колонке. Решение принимается по размеру всей строки, и пока она умещается, крупноватое поле спокойно лежит на месте.
Считают вынос бесплатным ускорением. Для запросов без этой колонки да, а вот выборка со звёздочкой по таблице с большими значениями становится дороже, чем кажется по числу строк.
Удаляют большие значения и ждут, что размер на диске упадёт сам. Место освобождает только очистка, причём служебная таблица раздувается отдельно и в размере основной таблицы не видна, если смотреть без учёта связанных объектов.