7786
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it
💡 На Хабре вышла мега годная статья: «Как обрабатывать 5 млн изменяющихся форм в минуту с SLI 99.99%»!
В этой статье:• О системе обработки огромного потока форм — от поиска до подачи объявлений;
• Подробно объясняется, зачем команде нужен уровень надёжности SLI 99.99%;
• Описаны оригинальные подходы к версионированию данных, изоляции изменений;
• Приводятся реальные схемы работы с SQL/NoSQL, кэшами и стратегиями graceful degradation при отказах.
🔊 Продолжайте читать на Habr!
Email должен быть уникальным только для активных пользователей?
Большинство реализуют это проверками в коде, SELECT перед INSERT, транзакциями или триггерами. PostgreSQL умеет делать это на уровне индекса:
INSERT INTO users (email) VALUES ('a@b.com');UPDATE users SET deleted_at = now() WHERE email = 'a@b.com';
Partial UNIQUE index — отличный способ фиксировать правила прямо в PostgreSQL.
👍 DataLemur — задачи для практики и подготовки к собеседованиям!
На сайте собраны вопросы разного уровня сложности: от базовых запросов до задач с JOIN, GROUP BY, подзапросами и оконными функциями. Формат ориентирован на реальные кейсы, такие задачи часто встречаются в работе и на собеседованиях. Удобный ресурс, чтобы закрепить знания.
📌 Оставляю ссылочку: datalemur.com
➡️ SQL Ready | #ресурс
Пройти видеоверификацию на бирже или фармить донаты на OnlyFans 😍
Создать виртуальную личность и устроиться на работу онлайн.
Это 1 из 1000 способов оседлать ИИ. А научиться работать с этим можно в этом канале. Там уже слили:
– Как получить много генераций [гайд]
– Промты, улучшающие ответы ChatGPT в 10 раз [скопировать]
– Дикие способы заработка на ИИ [читать]
⚡️ Сохраняйте, это мастхев на 2026 год: @neiropulse
IS NOT DISTINCT FROM - равенство без NULL!
Обычное сравнение через = ломается, если возможен NULL:
SELECT *
FROM users
WHERE email = 'admin@example.com';
SELECT *
FROM users
WHERE email IS NOT DISTINCT FROM NULL;
IS NOT DISTINCT FROM считает NULL = NULL и работает как настоящее равенство:sql
SELECT *
FROM users
WHERE (email, phone)
IS NOT DISTINCT FROM ('a@b.com', NULL);
OR … IS NULL.IS NOT DISTINCT FROM - способ сравнивать значения, когда NULL допустимое состояние, а не исключение.
📂 Напоминалка для работы с SQL JOIN!
Например, INNER JOIN возвращает только совпадающие строки из двух таблиц, а LEFT JOIN позволяет получить все записи из основной таблицы, даже если связанной записи нет.
На картинке — 4 самых используемых типа SQL JOIN, которые постоянно встречаются в рабочих запросах.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
☕️ Смотрите что нашел — Explainshell.
Вводишь любую команду в терминале, и он по частям объясняет, что делает каждая часть. Не просто man-ка, а понятный синтакс-анализ.
Особенно кайф для тех, кто работает в Linux/DevOps/CI среде и хочет разбираться, а не наугад копипастить из StackOverflow.
📌 Оставляю ссылочку: explainshell.com
➡️ SQL Ready | #ресурс
📂 Напоминалка по нормальным формам баз данных!
Например, 1NF требует атомарных значений, 2NF убирает частичные зависимости, а 3NF избавляет от транзитивных зависимостей.
На картинке — основные нормальные формы, которые полезны при проектировании SQL-баз данных.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
Оконные фреймы (ROWS и RANGE) — управление областью расчёта!
В оконных функциях важны не только PARTITION BY и ORDER BY, но и то, какие строки попадают в окно вычисления. За это отвечают оконные фреймы — ROWS и RANGE.
Таблица операций:
transactions(id, user_id, amount, created_at)
SUM(amount) OVER (
PARTITION BY user_id
ORDER BY created_at
)
ORDER BY и отсутствии явного фрейма в большинстве СУБД используется RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.created_at совпадают, сумма считается сразу по группе строк (peers).AVG(amount) OVER (
PARTITION BY user_id
ORDER BY created_at, id
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
)
ROWS формирует окно по количеству строк. Детерминированный ORDER BY необходим для воспроизводимого результата.SUM(amount) OVER (
PARTITION BY user_id
ORDER BY created_at
RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW
)
RANGE формирует окно по значениям ORDER BY. Поддержка и синтаксис интервалов зависят от СУБД; часто допускается только одно выражение в ORDER BY.ROWS — предсказуем по количеству строк, RANGE — удобен для временных интервалов и peer-групп, неявный фрейм может менять результат вычислений
Как выполнять сложные data-миграции, не ломая UNIQUE-ограничения?
Иногда нужно массово менять данные, временно нарушая UNIQUE, но итоговое состояние корректно:
BEGIN;
COMMIT:SET CONSTRAINTS users_email_uniq DEFERRED;
UPDATE/INSERT, даже если в процессе появляются дубликаты:UPDATE users
SET email = lower(email);
COMMIT;
ROLLBACK, без частичных изменений.UNIQUE.
UNION и UNION ALL — когда строки исчезают без ошибок!UNION удаляет дубликаты по всем выбранным колонкам, сравнивая строки целиком, поэтому результат может отличаться от ожиданий.
SELECT message FROM logs_app
UNION
SELECT message FROM logs_system;
message схлопнутся в одну строку, даже если это разные события — ошибки не будет.UNION ALL не удаляет строки из результата запросов, поэтому почти всегда работает быстрее: SELECT message FROM logs_app
UNION ALL
SELECT message FROM logs_system;
SELECT 'app' AS src, id, message FROM logs_app
UNION ALL
SELECT 'system' AS src, id, message FROM logs_system
ORDER BY src, id;
INTERSECT) в MySQL не поддерживается, альтернатива:SELECT DISTINCT a.message
FROM logs_app a
WHERE EXISTS (SELECT 1 FROM logs_system s WHERE s.message = a.message)
LIMIT 10;
UNION из-за совпадений между таблицами, используйте UNION ALL и проверяйте строки, встречающиеся в обоих источниках:SELECT message, COUNT(*) AS cnt, COUNT(DISTINCT src) AS sources
FROM (
SELECT message, 'app' AS src FROM logs_app
UNION ALL
SELECT message, 'system' AS src FROM logs_system
) t
GROUP BY message
HAVING sources > 1;
UNION — когда нужна дедупликация, UNION ALL — когда важна каждая строка и производительность.
Сравнение наборов и вычисление пересечения по ключу!
Нужно быстро получить пересечение двух таблиц по ключу? Используйте JOIN по колонке, которая логически должна совпадать в обоих наборах:
JOIN table_b b ON a.id = b.id
SELECT a.id
CREATE TABLE table_a(id int);
CREATE TABLE table_b(id int);
INSERT INTO table_a VALUES (1),(2),(3);
INSERT INTO table_b VALUES (2),(3),(4);
JOIN, вы увидите только 2,3 как пересечение наборов.
Find + Update в одном проходе!
Найдём строки с невозможными значениями и сразу подготовим их к UPDATE:
WITH c AS (SELECT id FROM products WHERE price < 0 LIMIT 3)
CTE c вернёт проблемные id.UPDATE products SET price = 0
CTE, чтобы не рассинхронизировать find/update:WHERE id IN (SELECT id FROM c);
CREATE TABLE products(id int PRIMARY KEY, price int);
INSERT INTO products VALUES (1,-10),(2,-5),(3,100);
find+update снова и убедитесь, что исправление точечное и атомарное.
Транзакция, которая берёт только свободные строки!
В конкурентной обработке задач важно не брать строку, уже заблокированную другой транзакцией, и не ждать её освобождения.
PostgreSQL делает это через:
FOR UPDATE SKIP LOCKED
BEGIN;
SELECT id FROM jobs WHERE status='queued' FOR UPDATE;
BEGIN;
SELECT id FROM jobs WHERE status='queued' FOR UPDATE SKIP LOCKED LIMIT 1;
SKIP LOCKED. Нет двойной обработки, ожиданий и внешних зависимостей.
Транзакции в SQL — почему частичные изменения хуже ошибки!
Работа с несколькими связанными таблицами в одном сценарии должна быть атомарной. Без TRANSACTION при автокоммите каждый UPDATE фиксируется отдельно — и есть риск получить несогласованное состояние.
Таблицы:
wallet(user_id, balance)
payments(id, user_id, amount, status)
done.UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
-- сбой соединения тут
UPDATE payments SET status = 'done' WHERE id = 55;
BEGIN;
UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
UPDATE payments SET status = 'done' WHERE id = 55;
COMMIT;
COMMIT изменения видны только в текущей сессии и не становятся устойчивыми. Если все шаги успешны — фиксируется сразу всё.BEGIN;
UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
UPDATE payments SET status = 'done' WHERE id = 55;
ROLLBACK;
ROLLBACK происходит именно при разрыве соединения или явном откате.UPDATE wallet
SET balance = balance - 100
WHERE user_id = 7 AND balance >= 100;
UPDATE payments
SET status = 'done'
WHERE id = 55 AND status = 'pending';
UPDATE выполняем в одной транзакции, затем проверяем rowcount: если любой запрос затронул 0 строк — ROLLBACK и обработка как ошибка.SELECT ... FOR UPDATE также работает только в той же транзакции, где будет обновление. Любая операция списания + фиксации платежа = транзакция.
Знали, что агрегаты можно фильтровать без CASE и подзапросов?
Многие пишут COUNT(CASE WHEN ...), хотя в SQL (например, в PostgreSQL) есть более декларативный способ - FILTER.
Фильтрация применяется к агрегатной функции, а не ко всей выборке:
COUNT(*) FILTER (WHERE status = 'paid')
FROM, а учитываются только внутри конкретного агрегата.COUNT(*) FILTER (WHERE status = 'failed')
FILTER работает не только с COUNT, но и с другими агрегатами:SUM(amount) FILTER (WHERE status = 'paid')
FILTER выразит намерение напрямую: агрегат считает только нужные строки, без лишней логики.
🚀 Yandex B2B Tech запускает сервис Managed Sharded PostgreSQL для горизонтального масштабирования PostgreSQL
PostgreSQL — самая популярная open-source СУБД, которой сегодня пользуются 55,6% профессиональных разработчиков. Но одна из главных её ограничений — отсутствие встроенного горизонтального масштабирования, что критично при обработке больших объемов данных.
Yandex B2B Tech решила эту задачу, запустив сервис , который позволяет шардировать PostgreSQL — то есть распределять данные по нескольким серверам. Это ускоряет работу систем, снижает риски и сокращает время вывода продуктов на рынок в 3-4 раза.
Технология уже проверена в реальных проектах Яндекса, таких как Яндекс ID, Яндекс Пэй и Едадил, а также успешно используется внешними клиентами.
Managed Sharded PostgreSQLдоступен на облачной платформе Yandex Cloud и помогает банкам и ритейлерам обрабатывать миллионы транзакций быстрее и надежнее.
Подробнее — ссылка
Partial index по стабильному селективному срезу!
В PostgreSQL частичный индекс особенно эффективен, когда в запросах регулярно повторяется один и тот же селективный предикат WHERE, а цель — быстро получить последние N записей по времени.
Таблица:
audit_logs(id, service, level, created_at, payload JSONB)
CREATE INDEX idx_billing_errors
ON audit_logs (created_at DESC)
WHERE service = 'billing' AND level = 'error';
buffer cache, уменьшает вероятность bloat и объём фонового обслуживания, а операции с индексом требуют меньше ресурсов.SELECT id, created_at, payload
FROM audit_logs
WHERE service = 'billing'
AND level = 'error'
AND created_at > NOW() - INTERVAL '1 day'
ORDER BY created_at DESC
LIMIT 15;
ORDER BY created_at DESC + LIMIT позволяет планировщику сделать Index Scan и остановиться рано, как только найдено нужное количество строк.all-visible (visibility map).INCLUDE:CREATE INDEX idx_billing_errors_top
ON audit_logs (created_at DESC)
INCLUDE (id)
WHERE service = 'billing' AND level = 'error';
CREATE INDEX idx_critical_errors
ON audit_logs (created_at DESC)
WHERE level = 'error'
AND payload @> '{"critical": true}';
SELECT id, service, created_at
FROM audit_logs
WHERE level = 'error'
AND payload @> '{"critical": true}'
ORDER BY created_at DESC
LIMIT 10;
❤️ Нашёл замечательную статью на Хабре: «Курс молодого бойца PostgreSQL»!
В этой статье:• Автор шаг за шагом показывает, как использовать ключевые возможности PostgreSQL;
• Приводятся понятные примеры SQL-запросов с объяснением, когда и почему применять те или иные конструкции;
• Рассматриваются полезные трюки - преобразование типов, агрегации и работа с массивами;
• Все примеры можно сразу запускать.
🔊 Продолжайте читать на Habr!
👩💻 В сеть вывалилась гигантская куча курсов и книг от топовых IT‑школ
Держи сотни гигабайт свежих уроков, и каждую неделю мы подкидываем ещё!
• 1612 ГБ — DevOps
• 1402 ГБ — Python
• 1300 ГБ — C, C++
• 1815 ГБ — Frontend
• 1515 ГБ — Backend
• 898 ГБ — ИБ, Хакинг
• 996 ГБ — Kotlin, Swift
• 212 ГБ — JavaScript
• 315 ГБ — Flutter
• 820 ГБ — Go, PHP
• 419 ГБ — Java, Rust
• 648 ГБ — GameDev
• 517 ГБ — Windows, Linux
• 998 ГБ — Дизайн (UX/UI)
• 617 ГБ — Нейросети (ML/RL)
• 546 ГБ — БД (SQL & NoSQL)
• 687 ГБ — Аналитика данных
• 115 ГБ — QA-тестирование
Подписывайся и не плати за то, что можно получить бесплатно
🖥 INDEX ONLY SCAN — когда SELECT не идёт в таблицу!
Когда в запросе нужны 2-3 конкретных поля, база может отдать их прямо из индекса, не трогая таблицу. Это особенно важно для тяжёлых таблиц, где каждый лишний lookup - потеря времени.
Сегодня в гайде:
• Как запрос выполняется только из индекса;
• Как убедиться, что таблица не читается (Heap Fetches: 0 в плане);
• Как проектировать индексы, чтобы покрывать SELECT полностью.
EXPLAIN — узнаём, как СУБД реально выполняет ваш запрос!
Команда EXPLAIN показывает, что делает база данных под капотом при выполнении SQL-запроса. Это помогает найти узкие места и понять, почему запрос может работать медленно.
Допустим, у нас есть запрос:
SELECT * FROM books WHERE author = 'Толстой';
EXPLAIN, чтобы посмотреть план выполнения:EXPLAIN SELECT * FROM books WHERE author = 'Толстой';
Table Scan или Seq Scan — это означает, что происходит полный просмотр таблицы. Такой способ может быть медленным, особенно при большом объёме данных.CREATE INDEX idx_author ON books(author);
EXPLAIN запрос может использовать Index Scan, что значительно быстрее.
Согласованное чтение данных внутри одной транзакции!
Иногда несколько SELECT должны работать с одной и той же версией данных, даже если параллельно идут изменения.
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
MVCC snapshot в момент первого statement внутри транзакции:SELECT COUNT(*) FROM orders;
SELECT читают один и тот же snapshot и не видят новые COMMIT из других сессий, при этом собственные изменения транзакции видны:SELECT SUM(amount) FROM orders;
COMMIT;
COMMIT snapshot освобождается, транзакция завершается.
💡 ThoughtSpot SQL Tutorial — продуктивное обучение и практика!
Материал построен вокруг реальных примеров и практики: от базовых SELECT, JOIN и агрегатов до сложных подзапросов и аналитических функций. Пояснения идут шаг за шагом, с визуальными примерами и задачами, которые помогают сразу закрепить навыки на практике.
📌 Оставляю ссылочку: thoughtspot.com
➡️ SQL Ready | #ресурс
☕️ Наткнулся на любопытную статью — «Embedded SQL с группировкой запросов: элегантный подход к управлению SQL в Go»!
В этой статье:• Автор показывает, как хранить и группировать SQL-запросы в одном .sql-файле по сущностям;
• Рассказывается, как использовать go:embed для встраивания этих файлов в бинарник и загружать запросы по имени;
• Представлен парсер, который разбирает .sql с именованными секциями;
• Показаны преимущества подхода: подсветка SQL в IDE, чистый Go-код и др.
🔊 Продолжайте читать на Habr!
📂 Напоминалка по структурам баз данных!
Например, Skiplist ускоряет поиск в памяти, Hash-индекс даёт доступ за O(1), а B-tree и LSM-дерево оптимизируют работу с диском и записью.
На картинке — 8 структур данных, которые стоит держать под рукой, чтобы понимать, как устроены индексы и хранение в БД.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
❤️ SQL-EX — интерактивный тренажёр с задачами!
Если хочешь учиться через практику, этот сайт отличный инструмент. Здесь ты пишешь запросы прямо в браузере, получаешь мгновенную обратную связь и видишь результат. Подойдёт для закрепления теории, подготовки к собеседованию или реальных задач в работе с бд.
📌 Оставляю ссылочку: sql-ex.ru
➡️ SQL Ready | #ресурс
❤️ 30-Days-of-SQL — тридцатидневный челлендж в обучении!
Репозиторий предлагает серию упражнений и заданий на каждый день, которые охватывают ключевые темы: выборки, агрегации, подзапросы, оконные функции и др. Формат один день - одна задача помогает не перегружаться и выстраивать структурированный план обучения. Отлично подходит для практики, подготовки к собеседованиям и укрепления знаний.
Оставляю ссылочку: GitHub 📱
📂 Напоминалка по HTTP-стеку для разработки и инфраструктуры!
Например, HTTP/2 ускоряет загрузку за счёт мультиплексирования, а HTTP/3 делает обмен ещё быстрее, используя QUIC поверх UDP — уже стандарт для современных браузеров и CDN.
На картинке — ключевые компоненты HTTP-экосистемы, которые важно держать под рукой.
Сохрани, чтобы не забыть!
➡ SQL Ready | #ресурс
😎 PopSQL Learn — быстрый и структурный старт в SQL!
Если хочешь разобраться с SQL не по документации, а через чёткие объяснения и примеры запросов, этот сайт точно пригодится. Темы здесь идут от базовых до сложных концепций, всё с примерами, которые можно сразу повторить. Удобно, когда нужна практика для проектов или собеседований.
📌 Оставляю ссылочку: popsql.com
➡️ SQL Ready | #ресурс