This media is not supported in your browser
VIEW IN TELEGRAM
Здесь разобраны основы SQL, проектирование баз данных, индексы, транзакции, MVCC, WAL, оптимизация запросов, репликация, бэкапы и многое другое. Подойдёт разработчикам, которые хотят системно изучить PostgreSQL и разобраться не только с SQL, но и с архитектурой, производительностью, эксплуатацией базы данных.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍5❤3🤝3
Хочешь заняться архитектурой, а вместо этого третий час пишешь одну и ту же типовую миграцию? Теперь это можно делегировать.
CatCode - агент, который работает с проектом сам: пишет миграции, чинит запросы, гоняет тесты, пока ты занят чем-то более интересным. Доступны все топовые модели:
😒 Claude Opus 5
🤖 GPT-6 Astra
😐 Grok 4.6
и многие другие.
Умный свитчер решит фоном, кому что отдать - рутину дешёвой модели, сложный таск - нейросети покруче. Один лимит дешевле зоопарка отдельных подписок - всего 900 рублей в месяц.
Оплата картой РФ или СБП, работает без VPN. Первые задачи бесплатно, просто зарегистрируйся и попробуй.
Делегируй рутину уже сегодня: catcode.dev
CatCode - агент, который работает с проектом сам: пишет миграции, чинит запросы, гоняет тесты, пока ты занят чем-то более интересным. Доступны все топовые модели:
и многие другие.
Умный свитчер решит фоном, кому что отдать - рутину дешёвой модели, сложный таск - нейросети покруче. Один лимит дешевле зоопарка отдельных подписок - всего 900 рублей в месяц.
Оплата картой РФ или СБП, работает без VPN. Первые задачи бесплатно, просто зарегистрируйся и попробуй.
Делегируй рутину уже сегодня: catcode.dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👎5
Оконный фрейм по группам значений!
Если по одной цене находится 50 товаров, вся эта пачка считается одной группой. Поэтому можно строить окна относительно соседних значений, не вычисляя
Ещё интереснее
Среднее здесь считается по соседним строкам, но текущая строка автоматически исключается.
🔥
➡️ SQL Ready | #совет
ROWS считает физические строки. GROUPS считает группы строк с одинаковым значением ORDER BY.SELECT price,
count(*) OVER (
ORDER BY price
GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)
FROM products;
Если по одной цене находится 50 товаров, вся эта пачка считается одной группой. Поэтому можно строить окна относительно соседних значений, не вычисляя
dense_rank() и не добавляя ещё один уровень запроса.Ещё интереснее
EXCLUDE, который можно использовать прямо внутри оконного фрейма:SELECT id,
avg(score) OVER (
ORDER BY created_at
ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING
EXCLUDE CURRENT ROW
) AS neighbors_avg
FROM measurements;
Среднее здесь считается по соседним строкам, но текущая строка автоматически исключается.
SELECT price,
sum(amount) OVER (
ORDER BY price
GROUPS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE GROUP
)
FROM sales;
EXCLUDE GROUP исключит из расчёта всю текущую peer-группу, а не только одну строку.GROUPS + EXCLUDE позволяют описывать сложные окна непосредственно в OVER, где обычно появляются dense_rank(), дополнительные CTE и self join.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥7❤4
Составные индексы: правила проектирования и типичные ошибки!
Составные индексы используются для ускорения запросов по нескольким колонкам, но порядок полей внутри индекса напрямую влияет на его эффективность.
Представим таблицу заказов, где часто выполняются запросы по пользователю и дате создания заказа.
Обычный индекс на каждую колонку не всегда является оптимальным решением. СУБД может использовать несколько индексов одновременно, но такой план не всегда будет эффективнее одного правильно спроектированного составного индекса.
Для частого сценария поиска заказов конкретного пользователя за период лучше создать составной индекс:
Такой индекс эффективно работает для запросов, где используется первая колонка индекса или полный набор колонок.
В B-tree индексе данные сначала сортируются по
Поэтому СУБД быстро находит записи пользователя и затем выполняет поиск по диапазону дат. Также индекс будет использоваться:
Но он плохо подходит для поиска только по второй колонке:
Причина в структуре B-tree: данные сначала организованы по первой колонке индекса.
Для такого запроса отдельный индекс по дате будет более подходящим:
Ещё одна распространённая ошибка — добавление большого количества колонок в индекс.
Каждый дополнительный столбец увеличивает размер индекса и стоимость операций записи.
Перед созданием индекса нужно анализировать реальные запросы приложения, а не добавлять поля на всякий случай.
Для такого запроса может быть эффективнее индекс, учитывающий фильтрацию и сортировку:
Правильно спроектированный составной индекс уменьшает количество операций чтения, снижает нагрузку на CPU и помогает оптимизатору выбрать более дешёвый план выполнения.
🔥 Главное правило простое: индекс создаётся под реальные запросы приложения, а не просто под структуру таблицы.
➡️ SQL Ready | #практика
Составные индексы используются для ускорения запросов по нескольким колонкам, но порядок полей внутри индекса напрямую влияет на его эффективность.
Представим таблицу заказов, где часто выполняются запросы по пользователю и дате создания заказа.
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
status VARCHAR(30),
created_at TIMESTAMP NOT NULL,
amount NUMERIC(10,2)
);
Обычный индекс на каждую колонку не всегда является оптимальным решением. СУБД может использовать несколько индексов одновременно, но такой план не всегда будет эффективнее одного правильно спроектированного составного индекса.
CREATE INDEX idx_orders_user
ON orders(user_id);
CREATE INDEX idx_orders_created_at
ON orders(created_at);
Для частого сценария поиска заказов конкретного пользователя за период лучше создать составной индекс:
CREATE INDEX idx_orders_user_created_at
ON orders(user_id, created_at);
Такой индекс эффективно работает для запросов, где используется первая колонка индекса или полный набор колонок.
SELECT *
FROM orders
WHERE user_id = 42
AND created_at >= '2026-01-01';
В B-tree индексе данные сначала сортируются по
user_id, а внутри одинаковых значений user_id — по created_at.Поэтому СУБД быстро находит записи пользователя и затем выполняет поиск по диапазону дат. Также индекс будет использоваться:
SELECT *
FROM orders
WHERE user_id = 42;
Но он плохо подходит для поиска только по второй колонке:
SELECT *
FROM orders
WHERE created_at >= '2026-01-01';
Причина в структуре B-tree: данные сначала организованы по первой колонке индекса.
Для такого запроса отдельный индекс по дате будет более подходящим:
CREATE INDEX idx_orders_created_at
ON orders(created_at);
Ещё одна распространённая ошибка — добавление большого количества колонок в индекс.
CREATE INDEX idx_orders_all_columns
ON orders(user_id, status, created_at, amount);
Каждый дополнительный столбец увеличивает размер индекса и стоимость операций записи.
Перед созданием индекса нужно анализировать реальные запросы приложения, а не добавлять поля на всякий случай.
EXPLAIN ANALYZE
SELECT *
FROM orders
WHERE user_id = 42
AND status = 'paid'
ORDER BY created_at DESC;
Для такого запроса может быть эффективнее индекс, учитывающий фильтрацию и сортировку:
CREATE INDEX idx_orders_user_status_created_at
ON orders(user_id, status, created_at DESC);
Правильно спроектированный составной индекс уменьшает количество операций чтения, снижает нагрузку на CPU и помогает оптимизатору выбрать более дешёвый план выполнения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍7🤝4