Представления (views)

Предпосылки: подзапросы и CTE (подзапросы, CTE), соединения (JOIN).

Партиционирование | Индексы

Дашборд аналитики показывает количество сотрудников, среднюю зарплату и использование бюджета по отделам. Запрос — 3 JOIN, 2 подзапроса, 25 строк SQL. Каждое открытие страницы перезапускает этот запрос. Если тот же отчёт нужен в двух разных местах приложения — запрос дублируется, и любое изменение схемы требует правки в обоих местах.

Представление (view, англ. «вид, взгляд») — именованный запрос, сохранённый в базе. Обращение к view выглядит как обращение к таблице, но данные вычисляются при каждом запросе.

CREATE VIEW

CREATE VIEW employee_details AS
SELECT e.id, e.name, d.name AS department, e.salary, e.hire_date
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

Теперь вместо повторения JOIN можно писать:

SELECT name, department, salary
FROM employee_details
WHERE salary > 70000;
 name | department  | salary
------+-------------+--------
 Анна | engineering |  90000
 Вера | engineering |  85000

View — это именованный запрос, а не копия данных. При каждом SELECT из view PostgreSQL выполняет сохранённый запрос заново. Данные всегда актуальны, но производительность определяется сложностью запроса внутри view.

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

CREATE OR REPLACE VIEW employee_details AS
SELECT ...;   -- заменить определение
 
DROP VIEW employee_details;
DROP VIEW IF EXISTS employee_details;

CREATE OR REPLACE позволяет изменить запрос view без её удаления и пересоздания.

Обновляемые представления

Простые view (один SELECT из одной таблицы, без GROUP BY, DISTINCT, JOIN, подзапросов) допускают INSERT, UPDATE, DELETE:

CREATE VIEW engineers AS
SELECT id, name, salary
FROM employees
WHERE department_id = 1;
 
UPDATE engineers SET salary = 95000 WHERE name = 'Анна';

Это обновит строку в базовой таблице employees. Для сложных view обновление невозможно (или требует триггеров INSTEAD OF).

View как слой доступа

Таблица employees содержит salary и ssn (номер социального страхования). Аналитикам нужны только name и department. Можно выдать column-level GRANT, но каждый новый столбец в таблице требует ревью — забытый GRANT на конфиденциальный столбец = утечка данных.

Альтернатива — view с безопасным набором столбцов:

CREATE VIEW employee_directory AS
SELECT e.id, e.name, d.name AS department, e.hire_date
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
 
REVOKE ALL ON employees FROM analyst_role;
GRANT SELECT ON employee_directory TO analyst_role;

Аналитики видят только то, что включено в view. Новый столбец в employees автоматически скрыт — он не в SELECT view. Доступ управляется через одну точку.

View ограничивает столбцы, но не строки: аналитик увидит все строки base table. Для ограничения по строкам — добавить WHERE в определение view или использовать row-level security (в PostgreSQL — RLS).

Для тяжёлых запросов, результат которых допустимо обновлять периодически, PostgreSQL предлагает материализованные представления — view, сохраняющие результат на диск.

Sources


Партиционирование | Индексы