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

Автор: @energy_it

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

Реклама на бирже: https://telega.in/c/sql_ready
Download Telegram
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
👍166🔥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
👍17🔥84👎1🤝1
NOT VALID constraints — как добавить CHECK и FOREIGN KEY на huge таблицу без долгой блокировки?

Обычно добавление 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍7🔥7
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ PostgreSQL Querying — практическое изучение SQL на PostgreSQL!

Здесь подробно разбираются запросы, работа с данными, фильтрация, JOIN’ы, агрегации и другие конструкции, которые постоянно используются в разработке. Материал подаётся последовательно и на примерах, поэтому намного проще понять логику запросов и научиться писать их самостоятельно.

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


➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍6🤝51
Антиджойн в SQL — как находить отсутствующие связи!

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

Таблицы:
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 | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍9🔥6
📂 Напоминалка по шардингу баз данных!

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

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

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍6🤝5
PostgreSQL умеет пропускать заблокированные строки без ожидания!

Большинство знают 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥146👍5
This media is not supported in your browser
VIEW IN TELEGRAM
🧐 SQL Tutorial — подробный гайд по SQL с примерами!

На сайте собрано множество обучающих материал по SQL: от базовых запросов SELECT и WHERE до JOIN, подзапросов, функций, сортировки и работы с таблицами. Всё объясняется простым языком с примерами запросов и постепенным усложнением тем, поэтому материал подойдёт как новичкам, так и тем, кто хочет систематизировать знания по бд.

📌 Оставляю ссылочку: ravesli.com

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍5🤝3
Все надоело и пропал интерес, чувствуешь себя амебой и хочется только залипать в телефоне. Бывает?

Homo Manifestans — канал для айтишников, у которых периодически опускаются руки и отключается мозг, ибо переработки и постоянная тревожность не приводят к другим исходам 🤗

✓ Как научиться отвлекаться от работы и отдыхать?
✓ Как совместить кучу рабочих задач и время с семьей?
✓ Как справиться с прокрастинацией?
✓ Как не растерять запал, даже если начальник и коллеги 💩 и кажется, что ничего не выходит?

Подписывайтесь на канал @vadimpetrovpsi и научитесь работать без упахивания, выгорания и ущерба для личной жизни!

Псс. Заходите в закреп — там много полезного, и даже бесплатный мини-курс по выходу из апатии:
👉 https://t.me/+4ZhNArjrIc83M2E6
Please open Telegram to view this post
VIEW IN TELEGRAM
👎1
Почему CHECK constraint может пропустить неправильные данные из-за NULL!

Редкая, но неприятная ловушка SQL: многие думают, что 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 | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
🐱 SQL, MySQL и PostgreSQL — один из лучших материалов для изучения баз данных!

Это обучающий материал с теорией, объяснениями и практическими задачами. Здесь разбираются устройство баз данных, связи между таблицами, индексы, нормализация, проектирование схем и многое др. Большой акцент сделан на понимании того, как правильно проектировать бд и решать задачи, которые часто встречаются на собеседованиях и в работе.

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


➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍7🤝31