SQL Ready | Базы Данных
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_c РКН: https://clck.ru/3QREBc Реклама на бирже: https://telega.in/c/sql_ready
Mostrar más📈 Análisis del canal de Telegram SQL Ready | Базы Данных
El canal SQL Ready | Базы Данных (@sql_ready) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 16 616 suscriptores, ocupando la posición 7 640 en la categoría Tecnologías y Aplicaciones y el puesto 39 717 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 16 616 suscriptores.
Según los últimos datos del 01 septiembre, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de 1 233, y en las últimas 24 horas de -2, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 12.49%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 6.17% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 2 075 visualizaciones. En el primer día suele acumular 1 025 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 23.
- Intereses temáticos: El contenido se centra en temas clave como sql, строка, users, индекс, user_id.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_c
РКН: https://clck.ru/3QREBc
Реклама на бирже: https://telega.in/c/sql_ready”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 02 septiembre, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
Оставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
CHECK constraint требует, чтобы условие всегда было TRUE. Но это не так, CHECK запрещает только FALSE. А результат UNKNOWN — пропускается.
Именно поэтому nullable-колонки внутри CHECK могут вести себя не так, как ожидает разработчик.
Допустим, есть таблица товаров:
products(
id,
price,
discount
)
Хотим запретить скидку больше цены:
ALTER TABLE products
ADD CONSTRAINT chk_discount_price
CHECK (discount <= price);
На первый взгляд всё выглядит правильно.
Теперь такой INSERT действительно не пройдёт:
INSERT INTO products(id, price, discount)
VALUES (1, 100, 150);
Потому что проверка: 150 <= 100 даёт FALSE. А CHECK constraint запрещает строки, где выражение возвращает FALSE. Но дальше начинается важный нюанс SQL и трёхзначной логики.
Вот такой INSERT уже может пройти:
INSERT INTO products(id, price, discount)
VALUES (2, 100, NULL);
И такой тоже:
INSERT INTO products(id, price, discount)
VALUES (3, NULL, 50);
Многие ожидают, что CHECK отклонит такие строки. Но SQL работает иначе, если в сравнении участвует NULL, результатом становится не TRUE и не FALSE, а: UNKNOWN
То есть:
150 <= 100 -- FALSE
NULL <= 100 -- UNKNOWN
50 <= NULL -- UNKNOWN
NULL <= NULL -- UNKNOWN
И вот здесь самая важная мысль: CHECK constraint считает строку валидной, если результат выражения — TRUE или UNKNOWN. Запрещается только явно FALSE.
Это поведение связано с SQL three-valued logic — логикой с тремя состояниями: TRUE, FALSE и UNKNOWN. Именно поэтому CHECK сам по себе НЕ заменяет NOT NULL. Если колонка обязательная — это нужно указывать отдельно.
Правильный вариант:
CREATE TABLE products(
id bigint PRIMARY KEY,
price numeric NOT NULL,
discount numeric NOT NULL,
CONSTRAINT chk_discount_price
CHECK (discount <= price)
);
Теперь NULL уже не сможет пройти, потому что NOT NULL сработает раньше CHECK. Но в реальных системах скидка часто может отсутствовать. То есть NULL — это нормальное состояние: скидки нет.
В таком случае constraint лучше писать явно и читаемо:
ALTER TABLE products
ADD CONSTRAINT chk_discount_price
CHECK (
discount IS NULL
OR discount <= price
);
Такой вариант намного понятнее при чтении схемы. Он явно показывает бизнес-логику: либо скидки нет, либо она не больше цены. Но здесь есть ещё один тонкий момент.
Если price остаётся nullable: price numeric, то выражение: discount <= price снова может вернуть UNKNOWN. Например:
discount = 50
price = NULL
Результат проверки: 50 <= NULL, будет UNKNOWN, а строка снова станет валидной.
Поэтому если цена обязательна — нужен отдельный NOT NULL:
price numeric NOT NULL
Похожая ситуация встречается с датами. Например:
CHECK (end_date >= start_date)
Разработчик может думать, что constraint гарантирует корректный диапазон дат. Но если end_date nullable, такой CHECK спокойно пропускает:
end_date = NULL
потому что результат сравнения снова UNKNOWN.
И это может быть абсолютно нормальным поведением. Например, если NULL означает: период ещё не завершён. Но если обе даты обязательны, это нужно фиксировать явно:
start_date date NOT NULL,
end_date date NOT NULL,
CHECK (end_date >= start_date)
🔥 Вывод: если в CHECK участвуют nullable-поля, constraint может пропускать строки из-за UNKNOWN, CHECK не заменяет NOT NULL. Для обязательных значений всегда нужен отдельный NOT NULL constraint.
➡️ SQL Ready | #практикаSKIP LOCKED только для очередей через SELECT ... FOR UPDATE. Но мало кто использует его для параллельной пакетной обработки внутри PostgreSQL.
Если несколько воркеров одновременно обрабатывают огромную таблицу задач:
SELECT id
FROM jobs
WHERE processed = false
FOR UPDATE;
Без SKIP LOCKED процессы начинают ждать друг друга даже при наличии свободных строк.
PostgreSQL позволяет просто пропускать уже занятые записи:
SELECT id
FROM jobs
WHERE processed = false
FOR UPDATE SKIP LOCKED;
Теперь каждый воркер мгновенно получает только свободные строки без ожидания и конфликтов.
Это можно встроить прямо в UPDATE:
WITH cte AS (
SELECT id
FROM jobs
WHERE processed = false
LIMIT 100
FOR UPDATE SKIP LOCKED
)
UPDATE jobs
SET processed = true
WHERE id IN (SELECT id FROM cte);
Получается параллельная обработка на уровне PostgreSQL без внешних систем очередей.
🔥 Аналогично строят высоконагруженные фоновые обработчики, обработку писем, биллинг и массовые пакетные операции.
➡️ SQL Ready | #советusers(id, email)
orders(id, user_id)
Многие пытаются писать через NOT IN:
id="x8d2qa"
SELECT *
FROM users
WHERE id NOT IN (
SELECT user_id
FROM orders
);
Но здесь есть проблема: если подзапрос вернёт хотя бы один NULL, результат может стать пустым.
Причина — логика NULL в SQL ломает сравнение NOT IN.
Решением может служить антиджойн через NOT EXISTS:
id="m4z7pk"
SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
SQL проверяет отсутствие связанной строки и сразу останавливается при первом совпадении.
Ту же задачу можно решить через LEFT JOIN:
id="f1q9vc"
SELECT u.*
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
WHERE o.id IS NULL;
LEFT JOIN оставляет все строки users, а WHERE o.id IS NULL отбирает только те, где совпадений не нашлось.
Этот паттерн и называется антиджойн — верни строки, для которых связи не существует.
Особенно полезно это в проверках целостности данных:
id="k6n2yb"
SELECT *
FROM orders o
WHERE NOT EXISTS (
SELECT 1
FROM users u
WHERE u.id = o.user_id
);
Так можно быстро найти битые записи с отсутствующими foreign key.
🔥 Антиджойны пригодятся в аналитике, ETL, аудитах данных и поиске проблемных связей между таблицами.
➡️ SQL Ready | #практикаВ описании она выглядела скучно, а по факту - одна из самых интересных компаний, с которыми я общался.Весь процесс - от первого собеседования до оффера - занял 4 дня. P.S. Попробовать Софи бесплатно можно будет 16 июня. Не пропусти анонс здесь.
Оставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
CHECK или FOREIGN KEY на большую таблицу рискованная операция, потому что PostgreSQL начинает сразу сканировать все старые данные.
ALTER TABLE orders
ADD CONSTRAINT orders_user_fk
FOREIGN KEY (user_id)
REFERENCES users(id);
На production-таблицах в сотни строк это может превратиться в очень долгую блокировку DDL.
Но в PostgreSQL есть фича — NOT VALID:
ALTER TABLE orders
ADD CONSTRAINT orders_price_check
CHECK (price > 0)
NOT VALID;
Без полного сканирования таблицы, сразу начинает проверять все новые записи. При этом старые строки пока не валидируются.
Позже ограничение можно провалидировать отдельно:
ALTER TABLE orders
VALIDATE CONSTRAINT orders_price_check;
Самое интересное — VALIDATE CONSTRAINT не блокирует обычный concurrent DML как классический ALTER TABLE.
То же самое работает и для FOREIGN KEY:
ALTER TABLE orders
ADD CONSTRAINT orders_user_fk
FOREIGN KEY (user_id)
REFERENCES users(id)
NOT VALID;
🔥 Это одна из самых полезных возможностей PostgreSQL для безопасных миграций, постепенного внедрения ограничений и наведения порядка в старых базах без длительного простоя.
➡️ SQL Ready | #советВ этой шпаргалке собраны ключевые команды для создания, изменения и удаления пользователей, назначения и отзыва прав, а также проверки текущих ролей и сессий. Они применяются при управлении безопасностью базы данных, настройке доступа и аналитической работе с ролями.
➡️ SQL Ready | #шпора• Разбирается, почему массивы в PostgreSQL — это отдельная модель хранения со своими ограничениями и компромиссами;
• Показываются скрытые проблемы массивов: потеря ссылочной целостности, особенности GIN-индексов, TOAST, MVCC и дорогостоящие обновления;
• Объясняется, как правильно работать с массивами, когда использовать JSONB, intarray, pgvector и в каких случаях массивы действительно оправданы.
🔊 Продолжайте читать на Habr!➡️ SQL Ready | #статья
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 | #совет🐾 АИСыч напоминает: б бы «Backup — это не стратегия. Стратегия — это проверенное восстановление».На курсе отдельно разбираем, как проектировать PostgreSQL-инфраструктуру так, чтобы система переживала сбои без потери критичных данных. 🎁 Для наших подписчиков действует скидка 20% по промокоду:
SQLREADY20
Записаться на курс прямо сейчас
А ещё больше практики, ИИ и ИБ — в MAX Академии, где сейчас проходит розыгрыш курса за 1 рубль 🔥
Реклама АНО ДПО ЦПК "АИС", ИНН: 7720346012, erid: 2SDnjdvRDWzОставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
