SQL Academy: всё о реляционных БД и SQL
10.7K subscribers
154 photos
1 video
2 files
29 links
По всем вопросам и коммерческим предложениям писать @LadanovNick

Купить рекламу: https://telega.in/c/sqlacademyofficial

Чат студентов SQL Academy
https://t.me/sqlacademyorg
Download Telegram
Бэкап vs снапшот vs реплика — простое объяснение

Зачем это знать?
В реальной работе регулярно случается одно из трёх: сервер падает, кто-то удаляет данные, выходит неудачное обновление.
Спасают три разных инструмента — бэкап, снапшот и реплика. Они дополняют, а не заменяют друг друга.

Три понятия «на пальцах»
💾 Бэкап (backup)
Это отдельная копия данных, из которой можно развернуть базу заново — даже на другом сервере, через день/неделю.

📸 Снапшот (snapshot)
Это «моментальный снимок» диска/тома в текущем состоянии (LVM/ZFS/EBS и т.п.).
🔹Создаётся быстро, удобно откатиться перед апдейтом.
🔹Хранится на том же хранилище → если диск/массив сломается, снимок пропадёт вместе с ним.

🪞 Реплика (replication)
Это вторая копия базы, которая почти в реальном времени «повторяет» изменения с основной.
🔹Нужна для отказоустойчивости и масштабирования чтения.
🔹Если на мастер попала ошибка/удаление, она уйдёт и на реплику.

Что решает каждый инструмент
Бэкап → «машина времени»
🔹Восстановить состояние за конкретный день/время.
🔹Долгое хранение (архив), юридические требования.

Снапшот → «быстрый откат»
🔹Перед деплоем/миграцией: если что-то пошло не так — откат за минуты.
🔹Клонирование окружения для тестов.

Реплика → «всегда доступно»
🔹Быстро переключиться при падении мастера (failover).
🔹Разгрузить чтение (направить часть трафика на реплику).

Риски и подводные камни ⚠️
Бэкап
🔹«Бэкап есть» не значит «восстановится» — обязательны регулярные тесты восстановления.
🔹Нельзя хранить единственную копию рядом с базой; нужна отдельная площадка и шифрование.

Снапшот
🔹Хранится на том же хранилище → общая точка отказа.

Реплика
🔹Может отставать (лаг) — отчёты «сейчас» иногда смотрят на прошлое.

Практические рекомендации
Минимум для проекта
1️⃣ Ежедневный бэкап (полный или инкрементальный) → хранить вне сервера + шифровать.
2️⃣ Раз в неделю — проверка восстановления на тестовом стенде (restore-drill).
3️⃣ Перед любым рискованным обновлением — снапшот тома.
👍237👌4👏2
Триггеры в MySQL 🚀

Триггеры в MySQL — это специальные процедуры, которые автоматически выполняются в ответ на определённые события внутри таблиц базы данных. Они срабатывают при выполнении операций вставки (INSERT), обновления (UPDATE) или удаления (DELETE) данных.

Для чего нужны триггеры 🔍
Триггеры используются для автоматизации выполнения задач в базе данных, что помогает обеспечить целостность данных. Например, они могут автоматически обновлять или проверять данные при изменении таблицы, запускать расчёты или создавать журнал изменений (логирование операций).

Создание триггера 🆕
Создать триггер можно с помощью команды CREATE TRIGGER. Например, триггер, который будет автоматически устанавливать текущую дату и время в поле last_updated при обновлении строки в таблице users:


CREATE TRIGGER before_user_update
BEFORE UPDATE ON users
FOR EACH ROW
SET NEW.last_updated = NOW();


Удаление триггера
Удалить триггер можно с помощью команды DROP TRIGGER. Например:

DROP TRIGGER before_user_update;

Полезный пример использования ℹ️
Предположим, в базе данных есть таблица orders с полями id, total и updated_at. Можно создать триггер, который будет обновлять updated_at каждый раз, когда меняется сумма заказа (total):


CREATE TRIGGER update_order_timestamp
BEFORE UPDATE ON orders
FOR EACH ROW
WHEN (OLD.total <> NEW.total)
BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END;

Этот триггер помогает отслеживать момент последнего изменения суммы заказа, что может быть полезно для аудита изменений или для обновления связанных систем, например, систем бухгалтерского учета.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍258🔥8
Мини-квиз по дате и времени в MySQL

1️⃣ Вопрос 1: Что вернёт запрос?

SELECT DATE_FORMAT(
STR_TO_DATE('16-08-2024 21:15', '%d-%m-%Y %H:%i'),
'%Y/%m/%d %H:%i'
);


a) 2024/16/08 21:15
b) 16/08/2024 21:15
c) 2024/08/16 21:15
d) Ошибка парсинга

Правильный ответ: c) 2024/08/16 21:15

2️⃣ Вопрос 2: Какой результат вернёт функция LAST_DAY?

SELECT LAST_DAY('2024-02-10');


a) 2024-02-28
b) 2024-02-29
c) 2024-03-01
d) NULL

Правильный ответ: b) 2024-02-29

3️⃣ Вопрос 3: Чему равна разница в минутах?

SELECT TIMESTAMPDIFF(
MINUTE,
'2024-08-16 08:30:00',
'2024-08-16 10:05:00'
);


a) 90
b) 95
c) 120
d) 155

Правильный ответ: b) 95

4️⃣ Вопрос 4: Что произойдёт при добавлении интервала, если пересекается полночь?

SELECT TIMESTAMP('2024-08-16', '23:00:00') + INTERVAL 2 HOUR;


a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00

Правильный ответ: c) 2024-08-17 01:00:00
🔥3411👍11
Мини-квиз

1️⃣ Вопрос 1: Что гарантирует LEFT JOIN?

SELECT c.id, o.id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;


a) Вернутся только клиенты с заказами
b) Вернутся все заказы, даже без клиентов
c) Вернутся все клиенты, даже если у них нет заказов
d) Дубликаты строк будут удалены

Правильный ответ: c) Вернутся все клиенты, даже если у них нет заказов

2️⃣ Вопрос 2: Что фильтрует группы после агрегирования?

SELECT department, COUNT(*) AS cnt
FROM employees
GROUP BY department
-- ?


a) WHERE cnt > 5
b) HAVING cnt > 5
c) ORDER BY cnt > 5
d) WINDOW cnt > 5

Правильный ответ: b) HAVING cnt > 5

3️⃣ Вопрос 3: Какой запрос лучше всего использует составной индекс (department, salary)?
a) WHERE salary > 1000
b) WHERE department = 'IT' AND salary > 1000
c) WHERE department LIKE '%IT%'
d) ORDER BY salary

Правильный ответ: b) WHERE department = 'IT' AND salary > 1000
👍29🔥107👌3
Триггеры в PostgreSQL ⚡️

Зачем они нужны?
Триггеры помогают базе сама выполнять рутину: обновлять метки времени, писать журнал изменений, проверять данные. Это экономит код в приложении и снижает ошибки.

Что такое триггер
Триггер — это правило «когда случится X, сделай Y».
🔹 Время: BEFORE (до операции) или AFTER (после).
🔹Событие: INSERT / UPDATE / DELETE.
🔹Уровень:
— FOR EACH ROW — для каждой затронутой строки;
— FOR EACH STATEMENT — один раз на весь запрос.
Важно: в PostgreSQL триггер всегда вызывает функцию (обычно на PL/pgSQL).

Мини-пример: авто-обновление `updated_at` при любом UPDATE

-- 1) Добавим столбец с текущим временем по умолчанию
ALTER TABLE users
ADD COLUMN updated_at timestamptz NOT NULL DEFAULT now();

-- 2) Функция, которую будет вызывать триггер
CREATE OR REPLACE FUNCTION trg_set_updated_at() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
-- записываем текущее время
NEW.updated_at := now();
-- возвращаем изменённую строку
RETURN NEW;
END$$;

-- 3) Сам триггер: срабатывает перед UPDATE каждой строки
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION trg_set_updated_at();


Полезно знать 🧠
🔹Временно отключить/включить:
ALTER TABLE users DISABLE TRIGGER set_updated_at;
ALTER TABLE users ENABLE TRIGGER set_updated_at;
🔹Удалить триггер:
DROP TRIGGER set_updated_at ON users;
🔹Если несколько триггеров одного типа — они срабатывают по алфавиту имён.
Давайте им понятные префиксы (t10_…, t20_…).

Где новички чаще всего ошибаются ⚠️
1️⃣ «Скрытая магия»: непонятно, что меняет данные.
Решение — документируйте триггеры и давайте им говорящие имена.
2️⃣ Массовые операции: FOR EACH ROW на миллионах строк может замедлить UPDATE. Если возможно — переносите часть логики в периодические задачи или используйте FOR EACH STATEMENT.
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍5👌4🗿2👏1
мы постоянно улучшаем наш сервис и нам важно ваше мнение 🙌
заполните, пожалуйста, короткую форму — это займет пару минут:
https://docs.google.com/forms/d/e/1FAIpQLSd5kdm4NfgquCKWptO83R9qmyuIZAyk1fSzK4v3fiTIp7D84w/viewform

🎁 бонус: премиум на нашей платформе получат 2 автора самых интересных предложений.
📌 в поле «ваши контактные данные» укажите ваш @username в Telegram.
🗓 сбор обратной связи — до 27 числа.

спасибо! 💛
Please open Telegram to view this post
VIEW IN TELEGRAM
13🔥7👍1
Blob в mysql или ссылки на файлы — как выбрать? 🗂️
Задача: нужно хранить файлы (фото, pdf, видео). Где их держать: прямо в базе (BLOB) или во внешнем хранилище (например, S3) и в БД — только ссылку? Разберёмся коротко и понятно.

Что такое blob и «ссылки»
🔹 BLOB — двоичные данные прямо в таблице MySQL (поле BLOB/LONGBLOB).
🔹 Ссылка — файл лежит во внешнем хранилище, а в БД мы храним URL + метаданные (имя, размер, тип).

Когда хранить в базе (blob) 📦
Подходит, если:
🔹файлы небольшие (аватарки, превью, ≤ ~1 МБ);
🔹важна атомарность: данные и файл сохраняются/откатываются вместе;
🔹проект простой, без CDN и стриминга.

Плюсы: просто, транзакционно, один бэкап.
Минусы: база быстро растёт, бэкапы тяжелее, отдавать большие файлы медленно.

Мини-пример

CREATE TABLE file_blobs (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
mime VARCHAR(100),
size INT,
-- для дедупликации
sha256 BINARY(32),
-- сам файл
data LONGBLOB NOT NULL,
created_at TIMESTAMP,
UNIQUE KEY (sha256)
);


Когда хранить снаружи (ссылки) 🔗
Подходит, если:
🔹файлов много или они крупные (фото/видео/доки);
🔹нужна раздача через CDN (быстрая доставка);
🔹важны дешёвое хранилище и лёгкие бэкапы БД.

Плюсы: масштабируемо, дёшево, быстро отдаётся.
Минусы: две системы (БД + хранилище).

Мини-пример

CREATE TABLE files (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
mime VARCHAR(100),
size INT,
sha256 BINARY(32),
-- https://... или s3://...
storage_url VARCHAR(2048) NOT NULL,
created_at TIMESTAMP,
UNIQUE KEY (sha256)
);


Быстрый чек-лист выбора
🔹Размер: маленькие → BLOB; большие → ссылка.
🔹Транзакционность (вместе с бизнес-данными): нужна → BLOB.
🔹 Отдача файлов пользователям: нужен CDN → ссылка.
🔹Бэкапы и восстановление: хочется лёгких дампов → ссылка.
🔹Стоимость хранения: экономим → ссылка.

Вывод
🔹BLOB хорош для маленьких файлов и строгой консистентности.
🔹Ссылки — почти всегда лучший выбор для больших объёмов, скорости и экономии.
16👍6🔥4
SQL-Academy-Interview-Questions-ru.pdf
1.2 MB
Топ-вопросы с собеседований по SQL + ответы 📝
Мы собрали самые популярные вопросы и варианты ответов — читайте по ссылке:
https://sql-academy.org/ru/interview-questions

Чтобы было удобнее, подготовили офлайн-версию (PDF). Сохраните и используйте, чтобы быстро освежить знания перед важным собесом.
📥 офлайн-версия — в файле к этому посту

удачи на собеседованиях! 💪
🔥44👍157😎5🙏2😢1
Мини-квиз по дате и времени в PostgreSQL

1️⃣ Вопрос 1: Парсинг даты одной функцией

SELECT to_date('16-08-2024', 'DD-MM-YYYY');

a) 16/08/2024
b) 2024-16-08
c) 2024-08-16
d) Ошибка парсинга

Правильный ответ: c) 2024-08-16

2️⃣ Вопрос 2: Разница в днях

SELECT DATE '2024-03-15' - DATE '2024-03-01';

a) 13
b) 14
c) 15
d) 16

Правильный ответ: b) 14

3️⃣ Вопрос 3: Номер недели (ISO) для актуальной даты

SELECT EXTRACT(WEEK FROM DATE '2026-01-01');

a) 0
b) 1
c) 52
d) 53

Правильный ответ: b) 1

4️⃣ Вопрос 4: Переход через полночь

SELECT TIMESTAMP '2024-08-16 23:00:00' + INTERVAL '2 hours';

a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00

Правильный ответ: c) 2024-08-17 01:00:00
🔥3212👍9👨‍💻7
Всем привет! На канале Data analysis | Анализ данных | DA разбираются темы и вопросы, которые должен знать аналитик данных, имеющий опыт 3-6 лет. Все темы взяты из реальных вакансий, опубликованных на hh.ru.

Будет полезно, если вы являетесь аналитиком данных (начинающим или опытным) или работаете по смежной профессии, либо просто интересуетесь базами данных, Python, SQL, экономикой и финансами и всеми производными от этих тем.

Список разобранных вопросов:

🐍 Python:
Эмбеддинги предложений
Алгоритм кластеризации
Кластеризация текстовой информации
Визуализация: Matplotlib
Визуализация: Seaborn
Python в Tableau
Python + SQL: Cx_oracle
Большие данные в Python: Dask
Массовая загрузка файлов в БД
Продвинутая запись в Excel: XlsxWriter
Аномалии в данных
Аномалии в данных: применение скользящих средних
Автоматизация подбора чисел
Анализ динамики


📖 SQL:
PARTITION (оконные функции)
PARTITION (партиционирование)
Процедуры: разбор IN | OUT | IN OUT
Процедуры: объявления и исключения
PACKAGE (пакеты)
Циклы LOOP, WHILE, FOR
CURSOR
Индексы
Представления (Views)
Материализованные и нематериализованные views
Hints (хинты)
EXPLAIN PLAN
TRIGGER (триггеры)


📖 Базы данных:
Какие бывают базы данных
Виды БД наглядно
ACID и BASE
OLAP-кубы
Проектирование баз данных
Разница между БД и DWH
Витрины данных
ETL и ELT процессы
Звездочка, снежинка, Data Vault
Слои данных в DWH
Нормализация


⚙️ Инструменты:
Обзор Hadoop
Обзор Hive
Обзор Impala
Обзор Airflow
Обзор ClickHouse
Tableau
Arenadata Catalog
Qlik Sense
Informatica PowerCenter


🐞 А/Б тестирование:
Основы А/Б тестов
А/Б тесты на практике
Математические методы проверки результатов
Инструменты А/Б тестирования


📊 Работа с данными:
Парадокс Симпсона
Банковские клиенты
Клиентская информация в банковском DWH
Банковские продукты
Продуктовая информация в банковском DWH
Счета, баланс и фин рез в банковском DWH
Качество данных
Метаданные
Source-to-Target Mapping


В ближайшем будущем будем разбирать 👇
— Больше про SQL и базы данных: архитектуру и т.п.
— Больше питоновских библиотек и кейсов
— Про банковские данные
— Актуальные инструменты, в частности BI-инструменты и ETL-инструменты
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥85👍2
Soft Delete, Hard Delete или Архив? Как правильно удалять данные 🗑️

Задача: Пользователь нажал «Удалить аккаунт». Что делать базе? Стереть навсегда? Скрыть? Или перенести в чулан? Разбираем три стратегии.

1️⃣ Hard Delete (Физическое удаление) 🧨
Классический DELETE. Данные исчезают, место освобождается.

Плюсы:
🔹 Максимальная скорость работы базы (таблицы компактные).
🔹 Соблюдение GDPR (право на забвение).
🔹 Нет проблем с уникальностью (email можно использовать повторно сразу).

Минусы: Данные не восстановить без бэкапа. Опасность «битых ссылок», если забыли настроить каскадное удаление (Foreign Keys).

2️⃣ Soft Delete (Мягкое удаление) 👻
Мы не удаляем строку, а ставим метку deleted_at = NOW(). Данные лежат на месте, но приложение делает вид, что их нет.

Плюсы:
🔹 Легко восстановить («Ой, я случайно!»).
🔹 Сохраняется история и связи.

Минусы:
🔸 Раздувание таблицы: База хранит тонны «мертвых» данных, индексы тормозят.
🔸 Сложность запросов: Везде нужно писать WHERE deleted_at IS NULL.
🔸 Проблема уникальности: Если bob@site.com удален «мягко», создать нового Боба с тем же email не даст уникальный индекс (нужен частичный индекс).

3️⃣ Archiving (Архивирование / Cold Storage) 📦
Гибридный подход. Данные удаляются из основной («горячей») таблицы, но перед этим переносятся в отдельную таблицу-архив (users_archive).

Как это работает:
🔹Стартуем транзакцию.
🔹INSERT данные в таблицу архива.
🔹DELETE данные из основной таблицы.
🔹Коммит.

Плюсы:
Основная таблица летает (в ней только активные данные).
История сохранена (в архиве).
Нет проблем с уникальными индексами в основной таблице.

Элегантный перенос одной командой (PostgreSQL) :

WITH moved_rows AS (
DELETE FROM users
WHERE id = 101
RETURNING *
)
INSERT INTO users_archive
SELECT * FROM moved_rows;
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥28👍94👎1👌1🆒1
SQL & AI: Друзья или враги?
Еще пару лет назад мы обсуждали, заменит ли нейросеть разработчика. В 2026 году ответ стал очевиден: AI не заменил SQL-специалиста, но он радикально изменил правила игры.
Сегодня разбираемся, как превратить AI в мощного союзника и где расставлены ловушки, в которые попадают даже мидлы.

🤝 Почему AI - ваш лучший друг
🔹Прощай, шаблонный код
Написать 10 однотипных JOIN или сложную структуру CASE WHEN нейросеть может за секунды. Это экономит до 40% времени на рутине.

🔹Объяснение чужого кода
Получили в наследство legacy-запрос на 200 строк без единого комментария? AI отлично справляется с декомпозицией и объяснением логики «человеческим» языком.

🔹Генерация синтетических данных
Нужно быстро наполнить таблицу для тестов, соблюдая типы данных и связи? AI сделает это лучше любого скрипта-заполнителя.

⚠️ Почему AI - коварный враг
Главная проблема в том, что AI галлюцинирует уверенно.

🔹Каша из диалектов

Модель может предложить изящное решение на функциях PostgreSQL (например, DISTINCT ON), которые просто не существуют или работают иначе в вашей версии MySQL или ClickHouse.

🔹Производительность — не приоритет по умолчанию
Если не попросить специально оптимизировать запрос, AI выдаст код, который просто «работает». Он часто предлагает вложенные подзапросы там, где эффективнее CTE или оконные функции, и редко думает об использовании индексов.

🔹Отсутствие контекста БД
Нейросеть не знает объема ваших данных, наличия индексов и специфики «железа». Запрос, который AI посчитал идеальным, может «положить» ваш прод в пиковую нагрузку.

💡 Как выжить в эпоху AI-SQL?
Чтобы оставаться востребованным профи, фокус должен сместиться с «написания кода» на его аудит и архитектуру.

🔹Валидация — это закон
Никогда не копируйте код из чата в консоль без проверки EXPLAIN ANALYZE.

🔹AI как ревьюер
Попробуйте обратный подход — скормите нейросети свой рабочий запрос и спросите: «Как это оптимизировать?». Иногда она подсвечивает неочевидные узкие места.

🔹Изучайте теорию глубже
Чем лучше вы понимаете работу планировщика запросов и индексов, тем проще вам будет увидеть «галлюцинацию» в ответе нейросети.

AI - это не замена мозга, а мощный инструмент. Он делает вас быстрее, но очень важно валидировать самостоятельно любой ее ответ.
25👍23🔥8💯1
🚀 Вопросы с собеседования на позицию intern аналитика в Тинькофф: разбор SQL 🚀

Сегодня мы разберем некоторые интересные вопросы по SQL, которые могут встретиться на собеседовании в Тинькофф. 📊🔍

1️⃣ Может ли измениться результат запроса, если в LEFT JOIN поменять местами таблицы ?

Да, если поменять местами таблицы в LEFT JOIN, результат запроса кардинально изменится. Все потому, что LEFT JOIN берет все строки из "левой" таблицы, дополняя их данными из "правой". Смена местами меняет логику: теперь "правая" становится "левой" и наоборот. Это влияет на то, какие строки и как будут включены в результат. 🔄

2️⃣ 5 + NULL это сколько?

В SQL, когда вы выполняете арифметическую операцию с NULL, результатом всегда будет NULL. Это связано с тем, что NULL представляет собой неопределенное значение, и любая операция с неопределенным значением также является неопределенной. Таким образом, 5 + NULL будет равно NULL.

3️⃣ Какие функции умеют возвращать значения из предыдущих/последующих строк для заданной строки таблицы ?

В SQL, чтобы работать с данными из строк до и после текущей, используются оконные функции. Эти функции обеспечивают доступ к значениям предыдущих/последующих строк:

ℹ️LEAD(): Получает данные из строки после текущей, позволяя смотреть вперед на заданное количество строк.

ℹ️ LAG(): Доступ к данным из строки перед текущей, предоставляя возможность анализировать предыдущие значения.

ℹ️ FIRST_VALUE() и LAST_VALUE(): Возвращают первое и последнее значение в наборе строк соответственно, идеально для сравнения текущих значений с крайними в диапазоне.

ℹ️ NTH_VALUE(): Дает значение из конкретной позиции в окне, полезно для нахождения конкретных точек данных в последовательности.

Для тех, кто хочет углубиться в тему оконных функций:
https://sql-academy.org/ru/guide/windows-functions

#задание_из_собеседования #tinkoff #intern #analytic
Please open Telegram to view this post
VIEW IN TELEGRAM
49👍23🔥12
Views vs Materialized Views: в чем разница?
Когда вы только начинаете работать с SQL, вам быстро надоедает писать один и тот же запрос на 20 строк с кучей джоинов. Чтобы не копипастить код, его можно сохранить прямо в базе. Для этого есть два способа: обычные Views (вьюхи) и материализованные.

Что такое View?
Это просто запрос, которому дали имя. База не создает новую таблицу и не копирует данные. Она просто запоминает ваш SELECT.
Когда вы пишете SELECT * FROM my_view, база «под капотом» подставляет ваш исходный код и выполняет его заново.

Представьте, что вам постоянно нужно видеть комнаты вместе с именами владельцев. Чтобы не джойнить таблицы каждый раз руками, делаем так:
CREATE VIEW room_owners AS
SELECT r.id, r.home_type, u.name as owner_name
FROM Rooms r
JOIN Users u ON r.owner_id = u.id;

Теперь можно просто писать SELECT * FROM room_owners. База будет каждый раз пересчитывать джойн.
Плюс в том, что данные всегда актуальные.
Минус: если в таблицах миллионы строк, такая View начнет подтормаживать.

Что такое Materialized View
Здесь база выполняет запрос один раз и сохраняет результат в отдельную скрытую таблицу. Это спасение для тяжелых расчетов. Например, если мы хотим посчитать общую выручку по каждой комнате за всё время:
CREATE MATERIALIZED VIEW room_stats AS
SELECT room_id, SUM(total) as total_earned
FROM Reservations
GROUP BY room_id;

Результат читается мгновенно, потому что сумма уже посчитана и лежит на диске. Но есть нюанс: данные в ней «застывают». Если пришла новая бронь, сумма не изменится, пока вы не обновите View командой:
REFRESH MATERIALIZED VIEW room_stats;


Что выбрать?
Все зависит от того, что вам важнее: скорость или актуальность. Если данные нужны «прямо сейчас» — делайте обычную View. Если вы строите отчет за прошлый месяц, который не меняется каждую секунду — Materialized View сэкономит кучу ресурсов.
28👍17🔥4👎1