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

Автор: @energy_c

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

Реклама на бирже: https://telega.in/c/sql_ready
Download Telegram
🖥 Разберем ALTER — команда для изменения структуры таблиц!

Добавить колонку, переименовать её, изменить тип или задать ограничение — всё это делается через ALTER TABLE. Один из важнейших инструментов в работе с готовыми таблицами.

➡️ SQL Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍157🤝4🔥3😁2
This media is not supported in your browser
VIEW IN TELEGRAM
😍 CitForum Database — большая база материалов по SQL и СУБД!

На сайте собрана крупная библиотека материалов по базам данных: SQL, проектирование БД, транзакции, индексы, оптимизация запросов и администрирование различных СУБД. Здесь можно найти статьи, учебные пособия, техническую документацию и обзоры по PostgreSQL, MySQL, Oracle, Microsoft SQL Server и другим системам управления базами данных.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍116🔥6🤝1
📂 Напоминалка по выбору NoSQL баз данных для проектов!

Например, MongoDB подходит для работы с гибкими документными структурами, Redis — для высокопроизводительного кэширования и хранения данных в памяти, а Cassandra — для распределённых систем с огромными объёмами данных и высокой доступностью.

На картинке — сравнение популярных NoSQL решений, их особенностей и основных сценариев использования: от поиска и аналитики до IoT, социальных сетей, e-commerce и real-time приложений.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6🤝5
Вычисляемые значения на стороне PostgreSQL!

Если значение полностью зависит от других колонок, не обязательно считать его перед каждым INSERT и UPDATE.

PostgreSQL умеет делать это сам и всегда гарантирует корректный результат.
INSERT INTO orders(price, quantity)
VALUES (100, 3);

SELECT total
FROM orders
WHERE id = 1;


Поле total заполнится автоматически. Его нельзя случайно забыть обновить или вычислить по старой формуле.
UPDATE orders
SET quantity = 5
WHERE id = 1;

SELECT total
FROM orders
WHERE id = 1;


После изменения исходных данных значение пересчитается автоматически.
ALTER TABLE products
ADD COLUMN search_name text
GENERATED ALWAYS AS (lower(name)) STORED;


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

🔥 Если колонка полностью вычисляется из других колонок, пусть этим занимается PostgreSQL. Логику проще поддерживать, когда вычисление в одном месте.

➡️ SQL Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍85🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
🧐 SQLler — интерактивный тренажёр для изучения SQL!

На сайте можно изучать SQL на практике, выполняя запросы прямо в браузере. Здесь собраны уроки по основным темам: подзапросы, агрегатные функции и другие конструкции, которые используются при работе с базами данных. Ресурс подойдёт новичкам, а также разработчикам и аналитикам, желающим закрепить знания с помощью практики.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝12🔥63👍2
📂 Напоминалка по работе с данными: Pandas — Polars — SQL!

Например, groupby() в Pandas и Polars выполняет роль GROUP BY в SQL, merge() аналогичен JOIN, sort_values() заменяет ORDER BY, а unique() работает как SELECT DISTINCT.

На картинке — основные операции для работы с таблицами: загрузка данных, просмотр строк, фильтрация, сортировка, группировка, объединение таблиц, переименование и удаление колонок в Pandas, Polars и SQL.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍8🔥5👎1
Почему EXISTS в SQL часто лучше использовать для проверки наличия данных, чем COUNT(*)!

Одна из распространённых задач в SQL — определить, существует ли хотя бы одна запись, соответствующая заданному условию. Для этого иногда используют COUNT(*), хотя его основное назначение — вычисление количества строк, а не проверка факта существования данных.

Например, есть таблица пользователей:
id | email
---+-----------------
1 | user@test.com
2 | admin@test.com
3 | test@test.com


Проверка наличия пользователя через COUNT(*):
SELECT
COUNT(*)
FROM users
WHERE email = 'user@test.com';


Такой запрос вернёт количество найденных строк. Если требуется только узнать, существует ли запись, получение точного количества всех совпадений не является необходимым.

Для проверки факта существования данных лучше подходит EXISTS:
SELECT EXISTS (
SELECT 1
FROM users
WHERE email = 'user@test.com'
);


EXISTS возвращает логическое значение: TRUE, если найдена хотя бы одна подходящая строка, и FALSE, если совпадений нет. При выполнении такого запроса оптимизатор базы данных может использовать стратегию с ранним завершением проверки после нахождения первого совпадения, так как дальнейший поиск для этой операции не имеет смысла.

Разница особенно заметна в больших таблицах и в часто выполняемых проверках внутри бизнес-логики: при создании пользователей, проверке связей между сущностями, наличии связанных данных и других условных операциях. Например, проверка наличия заказов пользователя через COUNT(*):
SELECT
COUNT(*)
FROM orders
WHERE user_id = 100;


Этот запрос отвечает на вопрос: сколько заказов существует у пользователя.

Если требуется только проверить наличие хотя бы одного заказа:
SELECT EXISTS (
SELECT 1
FROM orders
WHERE user_id = 100
);


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

COUNT(*) остаётся правильным выбором, когда необходимо получить фактическое количество записей:
SELECT
COUNT(*) AS orders_count
FROM orders
WHERE user_id = 100;


Например, для формирования отчётов, статистики или отображения количества элементов. При наличии индекса по колонкам, используемым в условии WHERE, EXISTS может эффективно использовать возможности оптимизатора и быстро определить наличие подходящей записи.

🔥 Важно понимать разницу: COUNT(*) отвечает на вопрос: сколько строк существует? EXISTS отвечает на вопрос: существует ли хотя бы одна строка? Выбор правильного оператора делает SQL-запросы более выразительными и лучше соответствует реальной задаче приложения.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥126👍6
This media is not supported in your browser
VIEW IN TELEGRAM
🧐 SQL Murder Mystery — изучаем SQL через детективное расследование!

Этот репозиторий превращает изучение SQL в интерактивную детективную игру. Вместо обычных упражнений вам предстоит расследовать преступление, постепенно находя улики и анализируя данные с помощью SQL-запросов. Такой формат позволяет не просто запоминать синтаксис, а учиться работать с реальными данными.

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

➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥125🤝5👍1
IS DISTINCT FROM — сравнение значений с NULL!

NULL обозначает отсутствие известного значения, поэтому стандартные операторы сравнения = и <> не позволяют корректно определить равенство или различие, если один из операндов содержит NULL.
Например:
NULL <> 'new value'


Результатом выражения будет NULL, а не TRUE или FALSE. Это связано с трёхзначной логикой SQL: результат сравнения с неизвестным значением также является неизвестным.

Поэтому проверки изменения данных с использованием обычных операторов сравнения требуют дополнительной обработки:
column <> new_value
OR (column IS NULL AND new_value IS NOT NULL)
OR (column IS NOT NULL AND new_value IS NULL)


Оператор IS DISTINCT FROM решает эту задачу, выполняя сравнение с явным учетом NULL и всегда возвращая логическое значение. Пример обновления пользователя только при фактическом изменении email:
UPDATE users
SET email = :new_email
WHERE id = :id
AND email IS DISTINCT FROM :new_email;


Если значения совпадают, строка обновлена не будет. Если одно значение содержит NULL, а другое — данные, оператор определит их как различные.

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


Результат:
false


В логике IS DISTINCT FROM два значения NULL считаются одинаковыми, так как оба представляют отсутствие значения. Без использования данного оператора аналогичная проверка требует дополнительных условий:
email <> :new_email
OR (email IS NULL AND :new_email IS NOT NULL)
OR (email IS NOT NULL AND :new_email IS NULL)


IS DISTINCT FROM заменяет такую конструкцию одним выражением и делает сравнение nullable-полей более предсказуемым.

При обновлении сущностей через API, синхронизации данных и импорте часто возникает ситуация, когда передаётся полный объект, хотя часть полей не изменилась. Обычный запрос:
UPDATE users
SET
email = :new_email,
name = :new_name
WHERE id = :id;


выполнит обновление независимо от фактического изменения значений.

В PostgreSQL это приводит к созданию новой версии строки в рамках MVCC, увеличению объёма WAL, дополнительным вызовам триггеров и генерации ненужных событий при использовании репликации или систем обработки изменений. Более точный вариант:
UPDATE users
SET
email = :new_email,
name = :new_name
WHERE id = :id
AND (
email IS DISTINCT FROM :new_email
OR name IS DISTINCT FROM :new_name
);


Такой подход позволяет выполнять обновление только при изменении данных. Он применяется в API, системах синхронизации, импортерах данных и интеграционных процессах.

🔥 IS DISTINCT FROM — оператор, который обеспечивает корректное сравнение значений с NULL и помогает избегать лишних операций записи в базе данных.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍6🔥5🤝1
📂 Напоминалка по порядку выполнения SQL-запросов!

Например, разработчик пишет запрос начиная с SELECT, но SQL-движок выполняет его иначе: сначала формирует источник данных через FROM, объединяет таблицы через JOIN, фильтрует записи через WHERE, группирует данные через GROUP BY и только после этого формирует итоговый результат.

На картинке — логический порядок выполнения SQL-операций.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍178🔥7
Почему JSONB в PostgreSQL не всегда быстрее JSON!

В PostgreSQL тип JSONB часто выбирают вместо JSON из-за возможности индексации и работы с операторами поиска. Но отличие между ними не только в скорости чтения — оно связано с тем, как PostgreSQL хранит, обрабатывает и изменяет данные.

Рассмотрим таблицу с JSONB-структурой:
CREATE TABLE events (
id SERIAL PRIMARY KEY,
payload JSONB
);


Добавим документ с вложенными данными:
INSERT INTO events (payload)
VALUES (
'{
"user": {
"id": 100,
"role": "admin"
},
"active": true
}'
);


При хранении JSONB PostgreSQL разбирает документ и сохраняет его во внутреннем бинарном представлении. Благодаря этому можно выполнять поиск по содержимому документа:
SELECT *
FROM events
WHERE payload @> '{"active": true}';


Оператор @> проверяет наличие указанного фрагмента внутри JSONB-объекта.

Для ускорения подобных запросов используется GIN-индекс:
CREATE INDEX idx_events_payload
ON events
USING GIN (payload);


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

При изменении одного поля PostgreSQL не изменяет отдельный элемент внутри JSONB-документа. Из-за механизма MVCC создаётся новая версия строки с новым значением JSONB:
UPDATE events
SET payload = jsonb_set(
payload,
'{user,role}',
'"moderator"'
)
WHERE id = 1;


Для небольших объектов это обычно не оказывает заметного влияния. Но большие JSONB-документы с частыми обновлениями могут увеличивать нагрузку на операции записи из-за необходимости создавать новые версии данных.

Ещё одно отличие связано с сохранением структуры документа. В типе JSON PostgreSQL сохраняет текстовое представление документа:
SELECT '{"b":2,"a":1}'::json;


В этом случае исходный порядок ключей сохраняется. JSONB хранит уже разобранную структуру документа:
SELECT '{"b":2,"a":1}'::jsonb;


В JSONB порядок ключей не сохраняется, поскольку PostgreSQL работает с внутренним структурированным представлением данных. Поэтому он лучше подходит для случаев, когда требуется поиск, индексация и работа с содержимым документа, а JSON — когда важно сохранить исходное представление данных.

Отдельно стоит учитывать особенности работы индексов. Например, запрос с извлечением значения через оператор ->> выглядит следующим образом:
SELECT *
FROM events
WHERE payload->>'active' = 'true';


А запрос с проверкой содержимого JSONB-объекта использует другой механизм доступа:
SELECT *
FROM events
WHERE payload @> '{"active": true}';


GIN-индекс эффективно работает с операторами JSONB, такими как проверка вхождения @>, проверка существования ключей ?, а также операторы проверки нескольких ключей ?| и ?&.

Однако GIN-индекс не ускоряет автоматически любые выражения с извлечением значений через ->>. Для таких случаев могут использоваться отдельные функциональные индексы.

Например, индекс для конкретного поля JSONB можно создать следующим образом:
CREATE INDEX idx_events_active
ON events ((payload->>'active'));


Если поле активно используется в фильтрации, сортировке или связях между таблицами, отдельная колонка часто будет эффективнее и проще для поддержки.

🔥 JSONB отлично подходит для хранения динамических структур, когда требуется гибкость схемы и возможность выполнять поиск по содержимому. Главное правило: JSONB — это инструмент для работы с полуструктурированными данными, а не способ заменить полноценную структуру реляционной базы данных.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🤝7🔥3
📂 Roadmap по изучению SQL для разработчиков и аналитиков!

На картинке — путь изучения SQL: от основ устройства базы данных и типов данных до запросов, операторов, функций, транзакций и управления доступом.

Собраны основные темы, которые стоит пройти: структура базы данных и объекты, команды работы с данными (DDL, DML, DQL, DCL, TCL), построение запросов, операторы, функции, типы данных и др.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥157👍6
Старые и новые значения в RETURNING!

До PostgreSQL 18 RETURNING не позволял получить одновременно старое и новое состояние строки. Если нужно было сравнить значения до и после UPDATE, приходилось писать CTE или выполнять дополнительный запрос.
WITH old_data AS (
SELECT id, price
FROM products
WHERE category = 'books'
)
UPDATE products p
SET price = p.price * 1.1
FROM old_data o
WHERE p.id = o.id
RETURNING
o.price AS old_price,
p.price AS new_price;


В PostgreSQL 18 старые и новые значения доступны прямо внутри RETURNING.
UPDATE products
SET price = price * 1.1
WHERE category = 'books'
RETURNING
id,
old.price AS old_price,
new.price AS new_price;


Это особенно удобно для журналирования изменений, аудита, API, которые сразу возвращают результат обновления, и любых сценариев, где нужно сравнить состояние строки до и после изменения.
DELETE FROM products
WHERE discontinued
RETURNING
old.id,
old.name,
old.price;


Та же идея работает и для DELETE: старое состояние строки доступно напрямую через old.

🔥 Небольшое изменение PostgreSQL 18, которое избавляет от лишних CTE и делает RETURNING заметно полезнее.

➡️ SQL Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍98
This media is not supported in your browser
VIEW IN TELEGRAM
🤔 DBA1 — материалы по администрированию PostgreSQL и базам данных!

Сайт посвящён изучению PostgreSQL и администрированию баз данных. Здесь собраны учебные материалы по установке и настройке PostgreSQL, работе с сервером, архитектуре СУБД, управлению пользователями, резервному копированию, репликации и другим задачам, с которыми сталкиваются DBA и backend-разработчики.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍6🤝42
📂 MySQL JOIN: шпаргалка по объединению таблиц!

Разобраны способы объединения таблиц, получение связанных данных, поиск совпадающих и отсутствующих записей, а также использование EXISTS и NOT EXISTS для проверки связей между таблицами.

На картинке — основные типы JOIN в MySQL с примерами SQL-запросов и визуальным объяснением.

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

➡️ SQL Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍76
This media is not supported in your browser
VIEW IN TELEGRAM
👍 PingCAP Talent Plan — практический курс по разработке системного уровня!

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

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

➡️ SQL Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
👍106🔥5
Разбираем почему REINDEX не заменяет VACUUM в PostgreSQL!

После большого количества операций UPDATE и DELETE в PostgreSQL часто используют команды VACUUM и REINDEX. Несмотря на то что обе относятся к обслуживанию базы данных, они решают разные задачи и не являются взаимозаменяемыми.

Создадим таблицу:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT
);


Добавим данные:
INSERT INTO users (email)
SELECT 'user' || g || '@mail.com'
FROM generate_series(1, 100000) AS g;


Удалим половину строк:
DELETE
FROM users
WHERE id <= 50000;


После выполнения DELETE строки не исчезают из файла таблицы сразу. PostgreSQL использует механизм MVCC, поэтому удалённые версии строк продолжают существовать до тех пор, пока они могут быть нужны активным транзакциям.

Для их обработки используется:
VACUUM users;


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

При этом обычный VACUUM обычно не уменьшает размер файла таблицы на диске — освободившееся место остаётся внутри таблицы и используется последующими операциями INSERT и UPDATE. Теперь перестроим индекс:
REINDEX INDEX users_pkey;


Или сразу все индексы таблицы:
REINDEX TABLE users;


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

При этом REINDEX не очищает таблицу от мёртвых версий строк и не заменяет выполнение VACUUM. Если же необходимо физически уменьшить размер таблицы и вернуть свободное место операционной системе, используется другая команда:
VACUUM FULL users;


VACUUM FULL полностью переписывает таблицу в новый компактный файл, освобождает место на диске, но требует блокировку уровня ACCESS EXCLUSIVE, поэтому на время выполнения таблица становится недоступной для чтения и записи.

Важно понимать, что в большинстве случаев регулярное обслуживание выполняет autovacuum. Ручной запуск VACUUM, VACUUM FULL или REINDEX обычно является следствием анализа конкретной проблемы, а не стандартной процедурой после большого количества изменений данных.

🔥 Главное отличие: VACUUM обслуживает таблицу и связанные с ней индексы, освобождая пространство, занятое мёртвыми версиями строк, для повторного использования. REINDEX занимается исключительно перестроением индексов. Эти команды решают разные задачи и используются в разных ситуациях.

➡️ SQL Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍5🔥4🤝1