Можно ли добавлять поле в таблицу вместо использования SELECT запроса
Что проверяют
Вопрос почти всегда про компромисс: хранить вычисляемое значение отдельной колонкой или считать его каждый раз в запросе. Интервьюер хочет услышать про свежесть данных, стоимость записи и способ заполнения, а не синтаксис ALTER TABLE. Следом спрашивают, как вы добавите такую колонку в таблицу на сотни миллионов строк.
Как отвечать
Можно, это обычная денормализация. Разложите варианты от «ничего не храним» до «храним всё»:
- вычисление в
SELECT: всегда актуально, ничего не хранится, но расчёт повторяется в каждом запросе. Хорошо для дешёвых выражений; - представление (
VIEW): формула в одном месте, запросы короче, скорость как у исходного запроса; - материализованное представление: результат хранится, чтение быстрое, но данные устаревают до очередного
REFRESH; - генерируемая колонка: в PostgreSQL
GENERATED ALWAYS AS (...) STOREDпересчитывается сама при записи строки, с 18 версии есть и виртуальные, которые считаются при чтении. Годится только для выражений над той же строкой; - обычная колонка, которую заполняет ETL: модель в dbt или шаг в Airflow. Самый гибкий вариант, но пересчёт при смене формулы или исходных данных на вас.
Колонку оправдывают три условия: значение дорого считать, его читают намного чаще, чем меняют, и по нему фильтруют или строят индекс.
Про добавление на большой таблице. В PostgreSQL с 11 версии ADD COLUMN без значения по умолчанию или с константным DEFAULT меняет только метаданные. А STORED-колонка или UPDATE на всю таблицу переписывают все строки, поэтому бэкфилл делают пачками. В ClickHouse есть MATERIALIZED-колонки и ALTER TABLE ... MATERIALIZE COLUMN для уже записанных данных.
Где спотыкаются
Отвечают «нет, SELECT не меняет структуру таблицы» и не замечают, что вопрос про выбор между хранением и расчётом.
Добавляют колонку и забывают, кто будет её обновлять. Через месяц она расходится с исходными данными, и два отчёта показывают разные цифры.
Запускают один UPDATE на миллиард строк в рабочее время: долгая транзакция, блокировки строк и раздутая таблица.