SQL Ready | Базы Данных
15.5K subscribers
1.26K photos
81 videos
2 files
644 links
Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Автор: @energy_it

РКН: https://clck.ru/3QREBc

Реклама на бирже: https://telega.in/c/sql_ready
Download Telegram
Почему NOT IN может вернуть пустой результат из-за NULL!

Одна из самых неприятных ловушек SQL — поведение NOT IN при наличии NULL. Запрос выглядит абсолютно корректно, но внезапно перестаёт возвращать строки.

Таблицы:
users(id)
bans(user_id)


Допустим, нужно получить пользователей, которых нет в bans. Часто пишут так:
SELECT *
FROM users
WHERE id NOT IN (
SELECT user_id
FROM bans
);


Пока в bans.user_id нет NULL — всё работает нормально. Но представим данные:
bans
-------
1
2
NULL


Теперь запрос внезапно вернет:
0 rows


Хотя пользователи без бана есть. Почему так происходит — SQL сравнивает условие примерно как:
id <> 1
AND id <> 2
AND id <> NULL


Но:
id <> NULL


не даёт TRUE или FALSE. Результат: UNKNOWN. А в WHERE проходят только TRUE. Из-за этого всё условие целиком перестаёт выполняться.

Это особенность трёхзначной логики SQL: TRUE, FALSE, UNKNOWN

Любое сравнение с NULL даёт UNKNOWN:
NULL = 1
NULL <> 1
NULL = NULL


Поэтому NOT IN с NULL внутри подзапроса становится опасным.

Безопасный вариант — NOT EXISTS:
SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM bans b
WHERE b.user_id = u.id
);


Почему EXISTS работает нормально: сравнение идёт построчно; NULL не ломает всю проверку; оптимизатор обычно хорошо превращает это в anti-join.

Ещё вариант — явно убрать NULL:
SELECT *
FROM users
WHERE id NOT IN (
SELECT user_id
FROM bans
WHERE user_id IS NOT NULL
);


Но на практике: NOT EXISTS обычно считается более безопасным и читаемым решением.

Отдельный момент: NOT IN () и NOT EXISTS могут давать разные планы выполнения в зависимости от СУБД. Но логически для nullable данных: NOT EXISTS почти всегда предпочтительнее.

Быстрая проверка проблемы:
SELECT COUNT(*)
FROM bans
WHERE user_id IS NULL;


Если такие строки есть — NOT IN уже потенциально опасен.

🔥 NOT IN и NULL плохо сочетаются. Если в подзапросе появляется хотя бы один NULL, условие может перестать возвращать строки вообще. Для таких проверок надёжнее использовать NOT EXISTS.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2110🔥5🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ SQL DEV — большая база для изучения SQL и PostgreSQL!

Здесь собрано огромное количество материалов по SQL: запросы, JOIN’ы, подзапросы, оконные функции, индексы, оптимизация и работа с PostgreSQL. Репозиторий отлично подходит как для изучения базы, так и для углубления в более сложные темы. Особенно полезно то, что здесь много практических примеров и разборов реальных SQL-конструкций.

Оставляю ссылочку: GitHub 📱


➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥127🤝5
📂 Напоминалка по оптимизации баз данных!

Например, индексы ускоряют поиск данных, а репликация помогает распределять нагрузку и повышать отказоустойчивость.

На картинке — 9 основных подходов для улучшения производительности базы данных, которые полезно держать под рукой.

Сохрани, чтобы не потерять!

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6🤝6
PostgreSQL может избежать полной сортировки таблицы при ORDER BY ... LIMIT!

Большинство думает, что ORDER BY всегда сортирует вообще всю таблицу. Но в PostgreSQL для LIMIT есть отдельная оптимизация — Top-N Heap Sort.
SELECT *
FROM orders
ORDER BY created_at DESC
LIMIT 10;


Если нужен только top-10 результат, PostgreSQL не обязан сортировать миллионы строк полностью. Вместо этого он держит в памяти только N лучших строк во время scan.

Это видно прямо в execution plan:
Sort Method: top-N heapsort


Особенно интересно становится на огромных таблицах, где полный sort мог бы уйти на диск:
SET work_mem = '4MB';

EXPLAIN ANALYZE
SELECT *
FROM events
ORDER BY created_at DESC
LIMIT 50;


Даже при маленьком work_mem PostgreSQL может избежать полной сортировки всех строк и работать заметно быстрее именно благодаря оптимизации Top-N.

А если добавить подходящий индекс:
CREATE INDEX idx_events_created_at
ON events (created_at DESC);


🔥 PostgreSQL вообще сможет обойтись без Sort и просто сделать Index Scan в нужном порядке.

➡️ SQL Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍8🤝6
Почему индекс может не использоваться, даже если он есть!

Очень частая ситуация: индекс создан, запрос написан вроде нормально, но SQL всё равно делает Seq Scan или Full Table Scan.

Имеем такую таблицу:
users(
id,
email,
created_at
)


Индекс:
CREATE INDEX idx_users_email
ON users(email);


Кажется, что такой запрос точно должен использовать индекс:
SELECT *
FROM users
WHERE email = 'test@example.com';


И обычно действительно будет Index Scan.

Но достаточно небольшой детали — и индекс может перестать использоваться. Например:
SELECT *
FROM users
WHERE LOWER(email) = 'test@example.com';


Проблема в том, что индекс построен по колонке: email. А в условии используется выражение:
LOWER(email)


Для оптимизатора это уже не то же самое условие. В итоге серверу часто приходится: применять LOWER() к строкам; сравнивать результат; читать гораздо больше данных, чем ожидалось.

Исправляется это expression/functional index:
CREATE INDEX idx_users_email_lower
ON users(LOWER(email));


То же самое часто происходит с датами:
SELECT *
FROM orders
WHERE DATE(created_at) = '2025-01-10';


Из-за:
DATE(created_at)


обычный индекс по created_at может не помочь, потому что функция применяется к колонке.

Правильнее писать диапазон:
SELECT *
FROM orders
WHERE created_at >= '2025-01-10'
AND created_at < '2025-01-11';


Так условие остаётся sargable — то есть пригодным для эффективного использования индекса.

Ещё одна частая проблема — преобразования типов. Например, плохо:
WHERE user_id::text = '100'


Если user_id — integer, то здесь преобразование применяется к колонке. В такой ситуации обычный индекс по user_id может не использоваться.

Правильнее:
WHERE user_id = 100


Важно: простое условие вида:
WHERE user_id = '100'


в некоторых СУБД может нормально привести литерал к integer и всё равно использовать индекс. Проблема чаще начинается там, где преобразуется сама колонка или выражение становится сложнее.

Популярная ошибка с LIKE:
WHERE email LIKE '%gmail.com'


Здесь обычный B-Tree индекс обычно бесполезен. Так как поиск начинается не с начала строки; сервер не может эффективно использовать упорядоченность индекса.

Если таблица маленькая: 100–1000 строк, то Full Scan может быть дешевле, чем прыжки по индексу.

🔥 Наличие индекса ещё не гарантирует его использование. Функции над колонками, преобразования типов, неправильные LIKE, OR-условия и устаревшая статистика могут сделать индекс бесполезным или менее выгодным для оптимизатора.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍6🤝5
This media is not supported in your browser
VIEW IN TELEGRAM
😎 SQL Cheatsheet — удобная шпаргалка для повседневной работы!

Этот репозиторий хорошо подойдёт тем, кто постоянно работает с базами данных и хочет быстро освежать в памяти нужные SQL-конструкции. Здесь всё подано компактно и по делу: запросы, JOIN’ы, агрегации, подзапросы и др. Особенно удобно использовать для подготовки к собеседованиям.

Оставляю ссылочку: GitHub 📱


➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍5🤝4
🎓 PostgreSQL должен быть спроектирован до первого инцидента.

В enterprise-среде PostgreSQL — это уже не просто база данных, а часть критичной инфраструктуры с требованиями к доступности, восстановлению, безопасности и мониторингу.

На курсе «Архитектура PostgreSQL для корпоративных систем» разбираем, как строить устойчивую PostgreSQL-инфраструктуру под реальные корпоративные нагрузки.

📌 В фокусе курса:
• High Availability (высокая доступность)
• Disaster Recovery (аварийное восстановление)
• failover-сценарии
• RPO/RTO
• резервирование и мониторинг
• архитектурные ошибки и точки отказа

🐾 АИСыч напоминает: б бы «Backup — это не стратегия. Стратегия — это проверенное восстановление».


На курсе отдельно разбираем, как проектировать PostgreSQL-инфраструктуру так, чтобы система переживала сбои без потери критичных данных.

🎁 Для наших подписчиков действует скидка 20% по промокоду: SQLREADY20
Записаться на курс прямо сейчас

А ещё больше практики, ИИ и ИБ — в MAX Академии, где сейчас проходит розыгрыш курса за 1 рубль 🔥


Реклама АНО ДПО ЦПК "АИС", ИНН: 7720346012, erid: 2SDnjdvRDWz
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍32
PostgreSQL умеет обновлять только реально изменившиеся строки и это может сильно сократить WAL и нагрузку!

Многие приложения делают UPDATE даже тогда, когда данные вообще не изменились.
UPDATE users
SET name = 'Alex'
WHERE id = 1;


Даже если name уже равен 'Alex', PostgreSQL всё равно создаст новую версию строки (MVCC), запишет WAL, обновит индексы и увеличит нагрузку на autovacuum.

Проверить это можно через системную статистику:
SELECT n_tup_upd
FROM pg_stat_user_tables
WHERE relname = 'users';


Чтобы избежать “пустых” UPDATE, можно сравнивать старые и новые значения прямо в WHERE:
UPDATE users
SET
name = $1,
email = $2
WHERE id = $3
AND (name, email) IS DISTINCT FROM ($1, $2);


IS DISTINCT FROM безопасно сравнивает даже NULL значения, в отличие от обычного !=:
SELECT
NULL = NULL,
NULL IS DISTINCT FROM NULL;


На highload-системах это может заметно уменьшить WAL, bloat, количество HOT/non-HOT update и нагрузку на autovacuum без изменения архитектуры.

➡️ SQL Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍155🔥4🤝1
✍️ Информативная статья вышла на Хабре: «Обратная сторона массивов в PostgreSQL»!

В этой статье:
• Разбирается, почему массивы в PostgreSQL — это отдельная модель хранения со своими ограничениями и компромиссами;
• Показываются скрытые проблемы массивов: потеря ссылочной целостности, особенности GIN-индексов, TOAST, MVCC и дорогостоящие обновления;
• Объясняется, как правильно работать с массивами, когда использовать JSONB, intarray, pgvector и в каких случаях массивы действительно оправданы.


🔊 Продолжайте читать на Habr!


➡️ SQL Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍7🤝51
🖥 Разбираем методы управления пользователями и правами!

В этой шпаргалке собраны ключевые команды для создания, изменения и удаления пользователей, назначения и отзыва прав, а также проверки текущих ролей и сессий. Они применяются при управлении безопасностью базы данных, настройке доступа и аналитической работе с ролями.

➡️ SQL Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍148🤝5
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ PostgreSQL Tutorial — подробная документация и учебник по PostgreSQL!

На сайте собрана большая база материалов по PostgreSQL: установка, настройка, SQL-запросы, работа с таблицами, индексами, функциями, транзакциями и администрированием базы данных. Материал подаётся последовательно. Отличный ресурс как для новичков, так и для разработчиков, которым нужен удобный справочник с примерами и практическими объяснениями.

📌 Оставляю ссылочку: postgresql.leopard.in.ua

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥84👎1🤝1