7786
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it
🖥 PostgreSQL: UPSERT и обработка конфликтов!В этом посте собраны основные механизмы PostgreSQL для вставки и обновления данных при конфликтах уникальности. Рассмотрены INSERT ... ON CONFLICT, DO NOTHING, условное обновление записей, использование EXCLUDED, обработка конфликтов по ограничениям, возврат результатов через RETURNING, синхронизация данных с MERGE и переопределение генерируемых идентификаторов.
➡️ SQL Ready | #шпора
Gemini Pro Argon на пол года по цене кофе?
Gemini Pro на 6 месяцев можно купить за 6$ (480₽ вместо 10.000₽), в 20 раз выгоднее чем официальная подписка.
> 4.0 Argon топ для вайбкодеров
> Nano Banana 2 PRO (картинки)
> Видео генерация (видео, нарезки, мувики)
> 5 ТБ облака в Google One
Для вайбкодеров есть API-токены в 2-3 раза дешевле официальных!
Приобрести можно в Магазине с 20.000+ покупок и 2000+ отзывов (есть возвраты и замены).
Как использовать SKIP LOCKED для параллельной обработки задач в postgresql!
При реализации очереди задач на postgresql несколько воркеров могут одновременно выбирать задания из одной таблицы. SELECT ... FOR UPDATE блокирует выбранные строки, но остальные воркеры могут ожидать освобождения тех же блокировок.
Для таких случаев postgresql поддерживает FOR UPDATE SKIP LOCKED, позволяющий пропускать строки, уже заблокированные другими транзакциями. Рассмотрим таблицу очереди:
CREATE TABLE jobs (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
status TEXT NOT NULL DEFAULT 'pending',
payload JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
UPDATE ... FROM:WITH next_job AS (
SELECT id
FROM jobs
WHERE status = 'pending'
ORDER BY created_at, id
FOR UPDATE SKIP LOCKED
LIMIT 1
)
UPDATE jobs j
SET status = 'processing'
FROM next_job
WHERE j.id = next_job.id
RETURNING j.id, j.payload;
SKIP LOCKED позволяет перейти к следующей подходящей записи без ожидания этой блокировки.UPDATE изменяет статус в той же транзакции, а RETURNING возвращает данные зарезервированной задачи. Для ускорения поиска доступных заданий можно использовать частичный индекс:CREATE INDEX idx_jobs_pending
ON jobs (created_at, id)
WHERE status = 'pending';
pending. При этом SKIP LOCKED не гарантирует строгий FIFO: заблокированные строки пропускаются.COMMIT), а обработку выполнять отдельно. При использовании autocommit транзакция завершается автоматически.processing. Поэтому обычно используют аренду задач (locked_until) и механизм повторного получения после её истечения. SKIP LOCKED пропускает заблокированные строки, но не исключает ожидание табличных блокировок.FOR UPDATE SKIP LOCKED позволяет нескольким воркерам конкурентно резервировать задачи без ожидания заблокированных строк. В сочетании с UPDATE ... RETURNING и частичным индексом это основа очереди на postgresql, но для надёжной обработки необходим механизм восстановления зависших задач.
🤔 PostgreSQL — разбор методов оптимизации!
Статья о том, как анализировать производительность PostgreSQL, находить причины медленных запросов и устранять узкие места. Материал помогает разобраться, какие факторы влияют на скорость обработки данных и как подходить к оптимизации системно. Основное внимание уделяется индексам, планам выполнения SQL-запросов, инструменту EXPLAIN ANALYZE и настройке PostgreSQL.
📌 Оставляю ссылочку: senzpo.ru
➡️ SQL Ready | #сайт
Используйте FETCH FIRST ... WITH TIES!
Когда нужно получить несколько первых строк по сортировке, обычный LIMIT может обрезать записи с одинаковым значением.
Например, запрос вернёт ровно три самых дорогих товара:
SELECT id, name, price
FROM products
ORDER BY price DESC
LIMIT 3;
WITH TIES:SELECT id, name, price
FROM products
ORDER BY price DESC
FETCH FIRST 3 ROWS WITH TIES;
RANK(), CTE и дополнительная фильтрация.WITH TIES сравнивает весь набор выражений из ORDER BY. Если добавить туда уникальный id, строки с одинаковой ценой уже не будут считаться равными.FETCH FIRST ... WITH TIES позволяет получать первые N строк вместе со всеми совпадениями на границе выборки без оконных функций.
Объединяйте соседние интервалы автоматически!
В PostgreSQL есть малоизвестный агрегат range_agg(), который объединяет пересекающиеся и соприкасающиеся диапазоны. Не нужны оконные функции, рекурсивные запросы и ручной поиск границ.
Допустим, в таблице bookings хранятся периоды занятости сотрудников.
SELECT employee_id,
range_agg(period) AS busy_periods
FROM bookings
GROUP BY employee_id;
multirange: набор непересекающихся интервалов. Пересекающиеся и соседние периоды PostgreSQL объединит автоматически, сохранив промежутки между ними.SELECT employee_id,
datemultirange(
daterange('2026-11-01', '2026-11-08')
) - range_agg(period) AS free_periods
FROM bookings
GROUP BY employee_id;
period имеет тип daterange, а результат ограничивается указанной неделей.range_agg() вместе с multirange позволяет объединять занятые интервалы и находить свободные периоды без сложных оконных запросов.
Почему оконная функция LAST_VALUE часто возвращает не последнюю строку!
Оконные функции позволяют выполнять вычисления по набору связанных строк без сворачивания результата через GROUP BY. Однако для некоторых функций результат зависит не только от PARTITION BY и ORDER BY, но и от границ оконного фрейма.
Особенно часто это проявляется при использовании LAST_VALUE. Рассмотрим задачу: для каждой операции необходимо вывести её сумму и сумму последней операции соответствующего счёта.
Предположим, данные представлены таблицей:
transactions(
id,
account_id,
amount,
created_at
)
LAST_VALUE (PostgreSQL):SELECT
id,
account_id,
amount,
LAST_VALUE(amount) OVER (
PARTITION BY account_id
ORDER BY created_at
) AS last_amount
FROM transactions;
LAST_VALUE должна возвращать сумму последней операции в пределах account_id. Но результат может совпадать с amount текущей строки.ORDER BY стандартный фрейм в PostgreSQL определяется как:RANGE BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW
CURRENT ROW в режиме RANGE включает группу строк с одинаковыми значениями сортировки — peer group. Рассмотрим операции одного счёта:id account_id amount created_at
-- ---------- ------ ----------
1 42 100 2026-01-10
2 42 200 2026-01-11
3 42 300 2026-01-12
LAST_VALUE результат будет:id amount last_amount
-- ------ -----------
1 100 100
2 200 200
3 300 300
SELECT
id,
account_id,
amount,
LAST_VALUE(amount) OVER (
PARTITION BY account_id
ORDER BY created_at, id
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS last_amount
FROM transactions;
LAST_VALUE возвращает сумму последней операции. Для приведённых данных last_amount будет равен 300 во всех строках.id обеспечивает однозначный порядок при совпадении created_at, если id уникален. Но есть ещё один нюанс — различие между ROWS и RANGE. Рассмотрим накопительную сумму:SELECT
id,
account_id,
amount,
SUM(amount) OVER (
PARTITION BY account_id
ORDER BY created_at
) AS running_total
FROM transactions;
id amount created_at
-- ------ ----------
1 100 10:00:00
2 200 10:00:00
3 300 11:00:00
RANGE обе операции с временем 10:00:00 принадлежат одной peer group. Результат накопительной суммы:id amount running_total
-- ------ -------------
1 100 300
2 200 300
3 300 600
created_at.ROWS и уникальный порядок сортировки:SELECT
id,
account_id,
amount,
SUM(amount) OVER (
PARTITION BY account_id
ORDER BY created_at, id
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW
) AS running_total
FROM transactions;
id amount running_total
-- ------ -------------
1 100 100
2 200 300
3 300 600
ROWS задаёт границы относительно позиций строк, а RANGE — относительно значений сортировки. При этом без уникального ORDER BY последовательность строк с одинаковыми ключами остаётся неопределённой.LAST_VALUE возвращает значение последней строки фрейма, а не максимальное значение столбца. Поэтому замена на MAX(amount) может изменить смысл расчёта. Поддержка оконных фреймов различается между СУБД, а порядок вывода строк без внешнего ORDER BY не гарантируется.ORDER BY внутри OVER определяет порядок вычисления, но не обязательно включает весь раздел во фрейм. Для LAST_VALUE и накопительных агрегатов важно явно задавать границы фрейма и детерминированный порядок сортировки.
Почему NOT EXISTS не всегда эквивалентен EXCEPT!
При сравнении двух наборов данных в sql часто используют NOT EXISTS или EXCEPT. Оба подхода позволяют найти строки, присутствующие в одном наборе и отсутствующие в другом. Однако их семантика различается при наличии дубликатов и NULL.
Рассмотрим задачу: найти товары поставщика, отсутствующие в основном каталоге. Создадим таблицы в PostgreSQL:
CREATE TABLE supplier_products (
product_id INT
);
CREATE TABLE catalog_products (
product_id INT
);
INSERT INTO supplier_products (product_id)
VALUES (10), (10), (20), (NULL);
INSERT INTO catalog_products (product_id)
VALUES (20), (NULL);
NOT EXISTS:SELECT s.product_id
FROM supplier_products s
WHERE NOT EXISTS (
SELECT 1
FROM catalog_products c
WHERE c.product_id = s.product_id
);
product_id
----------
10
10
NULL
DISTINCT.NULL также попадает в результат: сравнение NULL = NULL не возвращает TRUE, поэтому соответствие не обнаруживается. Теперь выполним EXCEPT:SELECT product_id
FROM supplier_products
EXCEPT
SELECT product_id
FROM catalog_products;
product_id
----------
10
EXCEPT. Во-первых, EXCEPT без ALL устраняет дубликаты, оставляя только уникальные строки. Во-вторых, при операциях над множествами два значения NULL считаются неразличимыми. Поэтому NULL, присутствующий в обоих наборах, исключается из результата.=. Если необходимо сохранить кратность строк, стандарт sql предусматривает EXCEPT ALL:SELECT product_id
FROM supplier_products
EXCEPT ALL
SELECT product_id
FROM catalog_products;
product_id
----------
10
10
EXCEPT ALL работает с мультимножествами. Количество экземпляров каждой строки определяется формулой:max(количество_слева - количество_справа, 0)
NOT EXISTS действует иначе: если найдено хотя бы одно соответствие, все строки внешнего набора с таким значением исключаются.(product_id, warehouse_id), причём warehouse_id может содержать NULL. Создадим таблицы:CREATE TABLE supplier_stock (
product_id INT,
warehouse_id INT
);
CREATE TABLE catalog_stock (
product_id INT,
warehouse_id INT
);
INSERT INTO supplier_stock VALUES
(10, NULL), (10, NULL), (20, 1);
INSERT INTO catalog_stock VALUES
(10, NULL);
(10, NULL):SELECT s.product_id, s.warehouse_id
FROM supplier_stock s
WHERE NOT EXISTS (
SELECT 1
FROM catalog_stock c
WHERE c.product_id = s.product_id
AND c.warehouse_id = s.warehouse_id
);
IS NOT DISTINCT FROM.EXCEPT без ALL, добавим DISTINCT:SELECT DISTINCT
s.product_id,
s.warehouse_id
FROM supplier_stock s
WHERE NOT EXISTS (
SELECT 1
FROM catalog_stock c
WHERE c.product_id IS NOT DISTINCT FROM s.product_id
AND c.warehouse_id IS NOT DISTINCT FROM s.warehouse_id
);
product_id | warehouse_id
-----------+-------------
20 | 1
EXCEPT без ALL. Все примеры рассчитаны на PostgreSQL. Поддержка отдельных конструкций зависит от СУБД и версии. По производительности универсального победителя нет: результат зависит от данных, индексов и плана выполнения.NOT EXISTS проверяет отсутствие соответствия, EXCEPT вычисляет разность множеств без дубликатов, а EXCEPT ALL учитывает кратность строк. При выборе конструкции важно учитывать NULL и повторяющиеся значения.
😍 Продвинутая оптимизация PostgreSQL — WAL, VACUUM и проектирование БД!
Статья о том, как повысить производительность PostgreSQL за счёт правильной настройки внутренних механизмов СУБД и проектирования структуры базы данных. Материал посвящён не только оптимизации SQL-запросов, но и причинам возникновения проблем с производительностью. Рассматриваются WAL (журнал предзаписи), VACUUM и AUTOVACUUM, очистка устаревших версий строк, управление транзакциями и проектирование таблиц.
📌 Оставляю ссылочку: dbserv.ru
➡️ SQL Ready | #сайт
🖥 MySQL — операторы и функции сравнения данных!Определение максимального и минимального значений с GREATEST() и LEAST(), лексикографическое сравнение строк через STRCMP(), NULL-безопасное сравнение с <=>, проверка принадлежности диапазону с BETWEEN и NOT BETWEEN, поиск совпадений в наборе значений через IN, а также сопоставление строк с шаблонами с помощью LIKE.
➡️ SQL Ready | #шпора
РОЗЫГРЫШ
Наши друзья из Пакета Безопасности решили устроить мощный розыгрыш призов!!!
Что у них в меню:
- Nothing Phone 3a (синий)
- Flipper Zero
- Футболка черного цвета
- Футболка белого цвета
- Годовая подписка на Gemini
- Книга Defensive Security
А что же надо сделать
⚡️ Быть подписанным на Пакет Безопасности
😈 Быть подписанным на Культ Безопасности
🧠 Быть подписанным на Кибер ПТУ
😎 Вступить в наш Чат
Сроки
29-го октября подведем итоги розыгрыша
Ну всё, погнали!
Удаляйте данные небольшими порциями!
В PostgreSQL у DELETE нет LIMIT. Но ограничить количество удаляемых строк можно через подзапрос.
DELETE FROM events
WHERE id IN (
SELECT id
FROM events
WHERE created_at < now() - interval '90 days'
LIMIT 1000
);
DELETE FROM events
WHERE id IN (
SELECT id
FROM events
WHERE created_at < now() - interval '90 days'
FOR UPDATE SKIP LOCKED
LIMIT 1000
);
DELETE через ограниченный подзапрос позволяет удалять данные порциями, сокращая длительность транзакций и нагрузку от массовой очистки.
😎 Индексы в PostgreSQL — подробное руководство по оптимизации SQL-запросов!
Статья о том, как работают индексы в PostgreSQL, зачем они нужны и в каких случаях помогают ускорить выполнение запросов. Материал объясняет принципы индексирования и влияние индексов на поиск, фильтрацию и обработку данных. Отдельное внимание уделяется ситуациям, когда индексы не используются или могут снижать производительность.
📌 Оставляю ссылочку: sqllab.ru
➡️ SQL Ready | #сайт
Требуются парни и девушки в возрасте 19–40 лет, желающие работать в сфере IT.
Опыт в программировании не нужен.
Завтра запускаем бесплатный онлайн-интенсив по Frontend-разработке, где будем показывать, как разрабатывать сайты и веб-приложения используя ИИ.
За 7 дней обучения без опыта ты:
1. Сделаешь реальный сайт сервиса доставки с нуля;
2. Добавишь JavaScript-логику, расчёты и трекинг;
3. Подключишь карты и маршрут доставки через API;
4. Превратишь сайт в Angular-приложение;
5. Подключишь backend и выложишь проект в продакшен;
6. Научишься использовать ChatGPT и Giga во Frontend-разработке;
7. Узнаешь 9 способов найти первый заказ на фрилансе даже без опыта.
А главное, ты увидишь, что разрабатывать сайты и приложения не так сложно, как кажется. И поймёшь, как тебе развиваться в этой профессии, чтобы уже через пару месяцев зарабатывать от 1000$ на вёрстке сайтов.
👉 Проскочить на интенсив бесплатно
🔥 С 2019 стабильно помогаем с обучением, практикой, зарабатывать на фрилансе и проходить собеседования.
Почему перенос условия из ON в WHERE меняет семантику LEFT JOIN
При использовании LEFT JOIN расположение предиката определяет не только состав результата, но и возможность сохранить строки левой таблицы без соответствий. Предикаты в ON участвуют в поиске совпадений, тогда как WHERE фильтрует результат соединения.
Рассмотрим запрос, который должен возвращать всех пользователей и количество их завершённых заказов:
SELECT
u.id,
COUNT(o.id) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
WHERE o.status = 'completed'
GROUP BY u.id;
o.status = 'completed' является null-rejecting: он не может вернуть TRUE, когда o.status содержит NULL. Поэтому строки, дополненные NULL при внешнем соединении, отбрасываются.SELECT
u.id,
COUNT(o.id) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
AND o.status = 'completed'
GROUP BY u.id;
0. Здесь принципиально использование COUNT(o.id): агрегат игнорирует NULL, тогда как COUNT(*) учитывает и строку, созданную внешним соединением при отсутствии совпадений.FILTER, сохранив соединение со всеми заказами:SELECT
u.id,
COUNT(o.id) FILTER (
WHERE o.status = 'completed'
) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
GROUP BY u.id;
FILTER позволяет применять независимые условия к разным агрегатам без повторного соединения таблиц:SELECT
u.id,
COUNT(o.id) FILTER (
WHERE o.status = 'completed'
) AS completed_orders,
COUNT(o.id) FILTER (
WHERE o.status = 'pending'
) AS pending_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
GROUP BY u.id;
WHERE исключает все строки с NULL со стороны правой таблицы, внешнее соединение в некоторых случаях может быть преобразовано во внутреннее. Такое преобразование сохраняет семантику исходного запроса, но не исправляет ошибочно выбранную логику фильтрации.EXPLAIN:EXPLAIN (ANALYZE, BUFFERS)
SELECT
u.id,
COUNT(o.id)
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
WHERE o.status = 'completed'
GROUP BY u.id;
Hash Join вместо Hash Left Join или другой тип внутреннего соединения. Конкретный алгоритм зависит от статистики, индексов и оценок стоимости, поэтому наличие LEFT JOIN в sql не гарантирует сохранение внешнего соединения в физическом плане.ON и WHERE при внешнем соединении — семантическое преобразование, а не просто изменение записи sql. Null-rejecting предикаты могут устранять строки без совпадений и создавать условия для упрощения LEFT JOIN до INNER JOIN оптимизатором.
Почему SELECT перед INSERT не защищает от дубликатов!
Рассмотрим пример на PostgreSQL: две транзакции одновременно пытаются создать пользователя с одинаковым email. Сначала создадим таблицу с ограничением UNIQUE:
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE
);
SELECT id
FROM users
WHERE email = 'admin@example.com';
INSERT INTO users (email)
VALUES ('admin@example.com');
INSERT и COMMIT, а вторая получит ошибку нарушения UNIQUE. Это типичная race condition (check-then-act). Без ограничения UNIQUE возникли бы дубликаты.ON CONFLICT без предварительного SELECT:INSERT INTO users (email)
VALUES ('admin@example.com')
ON CONFLICT (email) DO NOTHING
RETURNING id;
RETURNING вернёт её id. При конфликте вставка пропускается, а результат будет пустым. Если существующую запись необходимо обновить, используется DO UPDATE:INSERT INTO users (email)
VALUES ('admin@example.com')
ON CONFLICT (email)
DO UPDATE SET email = EXCLUDED.email
RETURNING id;
id не стоит: операция UPDATE может создавать новую версию строки, запускать триггеры и увеличивать нагрузку.id существующей записи без обновления, после DO NOTHING можно выполнить отдельный SELECT, учитывая уровень изоляции и возможность повторной попытки.SELECT перед INSERT не гарантирует уникальность при конкурентном доступе. Её обеспечивает ограничение UNIQUE, а ON CONFLICT позволяет корректно обрабатывать конфликты без предварительной проверки.
😎 Интересная статья попалась на Хабре: «Qwen3.8 27B обошла GPT-5.6 в SQL‑бенчмарке. И всё это — локально на ноутбуке»!
В этой статье:• Узнаете, как локальная Qwen3.8 27B показала результаты выше GPT-5.6 в SQL-бенчмарке DABstep;• Разберётесь, как запустить модель на ноутбуке с помощью LM Studio и DuckDB для анализа данных;• Сравните точность, скорость и стоимость локальных и облачных LLM, а также влияние квантования на производительность.
🔊 Продолжай читать на Habr!
Потолок зарплаты в IT — ВСЁ
Даже Senior-разработчики упираются в потолок. Дальше — менеджмент, смена компании или годы ожидания повышения.
Но есть другой путь — зарабатывать больше на уже накопленном IT-опыте. И для этого необязательно переучиваться с нуля.
Как именно, рассказывает Артём Алехин — экс-тимлид Сбера, работавший на валютных удаленках.
Он совмещал российский найм с валютным контрактом, зарабатывая $8–9 тысяч в месяц. Артем создал проект в рамках которого получил для своих 200 учеников 40+ офферов на 200к+.
Три направления, с которыми работает Артём:
— Валютная удалёнка: выход на зарубежный рынок и поиск офферов от $5 000.
— Монетизация экспертизы: превращать свой IT-опыт в доход через обучение и менторство
— Свой IT-продукт: запуск SaaS с проверкой спроса сервиса для селлеров.
Артём помогает выбрать подходящий путь и выстроить стратегию роста дохода, чтобы перестать зависеть от одного работодателя.
Переходи в канал Артёма и изучай: @artem_itishnaya
🖥 MySQL: проверка и очистка данных!В этом посте собраны основные функции MySQL для проверки, очистки и преобразования данных. Рассмотрены работа с регулярными выражениями, поиск и замена подстрок, удаление лишних пробелов, обработка пустых значений, преобразование типов и проверка корректности JSON.
➡️ SQL Ready | #шпора
📂 Шпаргалка по структуре каталогов Linux!
Например, /etc содержит системные конфигурации, /var используется для хранения логов и изменяемых данных, а /proc предоставляет информацию о процессах и состоянии ядра.
На картинке — основные каталоги с кратким описанием их назначения и роли в файловой системе.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
🚀 29 октября Arenadata проведёт техническую онлайн-конференцию ArenaTech
На ArenaTech инженеры Arenadata расскажут, как устроены продукты компании изнутри, поделятся опытом решения сложных инженерных задач и представят ключевые направления технологического развития.
🟢Основные темы конференции:
🔜СУБД: архитектура, развитие и эксплуатация. Обсудим планы развития Arenadata DB (ADB) и Greengage DB, новые возможности MPP-СУБД, включая hot standby, вопросы безопасности и устранения уязвимостей. Отдельное внимание уделим утилите ggrebalance, которая позволяет сокращать число сегментов кластера и заменять хосты с сохранением равномерного распределения данных.
🔜Платформа данных: безопасность и Kubernetes. Расскажем об управлении секретами и доступом в Arenadata Hyperwave (ADH) с использованием OpenBao. Разберём особенности переноса Impala, Trino и Spark в Kubernetes: интеграцию с Kerberos, разработку операторов, адаптацию Spark и использование Celeborn и YuniKorn.
🔜Инструменты: кластерный менеджер, документация, ИИ-поиск. Поделимся опытом организации процессов разработки технической документации и расскажем, как создавались интеллектуальный поиск и ИИ-ассистент, упрощающие поиск информации в документации многокомпонентной платформы данных. Также расскажем про развитие нашего кластерного менеджера ADCM.
После каждого доклада участники смогут задать вопросы спикерам в рамках Q&A-сессии.
Конференция будет интересна разработчикам, дата-инженерам, администраторам СУБД, архитекторам, DevOps-инженерам и техническим руководителям.
🗓 29 октября, 12:00 МСК
Формат: онлайн 🔛
Программа и регистрация
🐱 PostgreSQL Cookbook — практический справочник по работе с PostgreSQL на русском языке!
Материалы представлены в формате практических примеров: конкретная задача, способ её решения и пример SQL-кода. Такой формат позволяет не только изучать возможности PostgreSQL, но и использовать справочник непосредственно во время разработки. Особенно полезен, когда нужно разобраться с определённой конструкцией SQL, подобрать подходящий запрос или найти решение типовой задачи.
📌 Оставляю ссылочку: dsbasko.github.io
➡️ SQL Ready | #сайт
🧐 Годная статья лежит на Хабре: «Как мы разрешили чтение с реплик PostgreSQL — и почему шесть лет говорили „нет“»!
В этой статье: • Узнаете, почему чтение с реплик PostgreSQL может угрожать отказоустойчивости и приводить к проблемам с актуальностью данных;• Разберёте, как организовать маршрутизацию запросов через Patroni, Consul и PgBouncer с учётом отставания репликации;• Посмотрите, как перенос части запросов на реплики помог снизить пиковую нагрузку на primary и какие риски при этом остались.
🔊 Продолжай читать на Habr!
Обновляйте агрегаты одним запросом!
Когда нужно пересчитать статистику по пользователям, не обязательно сначала получать агрегаты, а затем обновлять каждую запись отдельно.
PostgreSQL позволяет объединить INSERT ... SELECT с ON CONFLICT:
INSERT INTO user_stats (user_id, total)
SELECT user_id, sum(amount)
FROM payments
GROUP BY user_id
ON CONFLICT (user_id)
DO UPDATE
SET total = EXCLUDED.total;
GROUP BY вычисляет суммы, а ON CONFLICT обновляет существующие записи или добавляет новые.user_stats(user_id) должно быть ограничение уникальности. Можно сразу пересчитывать несколько показателей:INSERT INTO user_stats (user_id, total, orders_count)
SELECT user_id, sum(amount), count(*)
FROM payments
GROUP BY user_id
ON CONFLICT (user_id)
DO UPDATE SET
total = EXCLUDED.total,
orders_count = EXCLUDED.orders_count;
INSERT ... SELECT ... ON CONFLICT позволяет пересчитывать и сохранять агрегаты одним запросом, без циклов и промежуточной обработки в приложении.
Почему ON CONFLICT DO NOTHING может скрывать ошибки в данных
В PostgreSQL ON CONFLICT DO NOTHING позволяет пропускать вставку строк при нарушении уникальности. Однако без указания конкретной цели конфликта PostgreSQL учитывает все подходящие уникальные ограничения и индексы. Из-за этого операция может быть пропущена по причине, которую бизнес-логика приложения не предусматривала.
Допустим, есть таблица пользователей:
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE
);
INSERT INTO users (email, username)
VALUES ('alex@example.com', 'alex');
INSERT INTO users (email, username)
VALUES ('maria@example.com', 'alex')
ON CONFLICT DO NOTHING;
ON CONFLICT DO NOTHING без указания цели конфликта обрабатывает нарушения уникальности по всем подходящим уникальным ограничениям и индексам.email уникален, но username = 'alex' уже существует. Если приложение проверяет только успешность выполнения SQL-запроса, оно может ошибочно считать регистрацию завершённой.INSERT INTO users (email, username)
VALUES ('maria@example.com', 'alex')
ON CONFLICT (email) DO NOTHING;
email. Нарушение уникальности username приведёт к ошибке 23505 (unique_violation).RETURNING:INSERT INTO users (email, username)
VALUES ('alex@example.com', 'alex2')
ON CONFLICT (email) DO NOTHING
RETURNING id;
id. Если вставка пропущена из-за конфликта по email, результат будет пустым. Это позволяет приложению отличать успешную вставку от пропущенной операции без дополнительного SELECT. Важно учитывать, что RETURNING при DO NOTHING не возвращает существующую строку и не сообщает причину конфликта.ON CONFLICT DO NOTHING важно явно указывать цель конфликта, если бизнес-логика допускает дубликаты только по определённому ключу. В сочетании с RETURNING это позволяет контролировать результат вставки, не скрывая нарушения уникальности по другим ключам.
📂 Как работает Git: наглядная шпаргалка!
Основные команды Git и схема взаимодействия между рабочей директорией, индексом (staging area), локальным и удалённым репозиториями.
На схеме также показано, как работают git fetch, git pull и другие команды для управления изменениями и синхронизации репозиториев.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
Выучить программирование — это только половина дела.
Нужно ещё найти работу 👨💻
Можно потратить месяцы на обучение, собрать портфолио и подготовить резюме, но так и не понять, где искать подходящие вакансии.
Поэтому хочу поделиться инструментом, который может упростить эту задачу.
Это IT-проект на базе нейросети, который помогает искать вакансии и находить возможности для трудоустройства. Вместо того чтобы тратить всё свободное время на поиск, можно воспользоваться ИИ и сосредоточиться на подготовке к собеседованиям и развитии навыков.
Ускоряйте массовую загрузку через FREEZE!
При загрузке данных в новую таблицу PostgreSQL может сразу пометить строки как замороженные. Для этого у COPY есть малоизвестная опция FREEZE.
BEGIN;
CREATE TABLE events_import (
id bigint,
payload jsonb
);
COPY events_import
FROM '/data/events.csv'
WITH (FORMAT csv, FREEZE true);
COMMIT;
FREEZE позволяет избежать последующей работы по заморозке загруженных строк. Но есть условие: таблица должна быть создана или очищена через TRUNCATE в текущей подоперации транзакции.BEGIN;
TRUNCATE events_import;
COPY events_import
FROM '/data/events.csv'
WITH (FORMAT csv, FREEZE true);
COMMIT;
FREEZE не отключает обычные проверки ограничений и не гарантирует ускорения самого импорта. Его преимущество — уменьшение будущей работы VACUUM по заморозке строк.COPY FREEZE при полной загрузке новых или очищенных таблиц, чтобы сократить последующую работу по обслуживанию данных.
📂 16 паттернов программирования, которые должен знать каждый разработчик!
Например, Two Pointers помогает эффективно работать с массивами, Sliding Window — находить подмассивы по заданным условиям, а Dynamic Programming — решать сложные задачи через повторное использование результатов подзадач.
На картинке — 16 популярных алгоритмических паттернов и структур данных, которые пригодятся на технических собеседованиях.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
⚡️ В сети начали массово сливать IT-курсы и книги известных онлайн школ
Вот отсортированная база с тонной материала (постепенно пополняется):
(363 видео, 87 книги) — Python
(117 видео, 53 книги) — ВАЙБКОД
(174 видео, 91 книги) — DevOps
(415 видео, 68 книги) — Frontend
(137 видео, 93 книги) — DS/ML
(143 видео, 33 книги) — ИБ/Хакинг
(352 видео, 89 книги) — С/С++/C
(343 видео, 87 книги) — Java/QA
(176 видео, 32 книги) — Git/Linux
(167 видео, 53 книги) — PHP/1С
(227 видео, 83 книги) — SQL/БД
(114 видео, 77 книги) — Сисадмин
(107 видео, 43 книги) — BA/SA
(181 видео, 32 книги) — Go/Rust
(167 видео, 43 книги) — Kotlin/Swift
(112 видео, 24 книги) — Flutter
(113 видео, 82 книги) — GameDev
(183 видео, 37 книги) — Дизайн
(136 видео, 33 книги) — PM/HR
Скачивать ничего не нужно — все выложили в Telegram