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.
DDL, DML, DQL, DCL, TCL), построение запросов, операторы, функции, типы данных и др.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс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 | #практикаSELECT, но SQL-движок выполняет его иначе: сначала формирует источник данных через FROM, объединяет таблицы через JOIN, фильтрует записи через WHERE, группирует данные через GROUP BY и только после этого формирует итоговый результат.
На картинке — логический порядок выполнения SQL-операций.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс= и <> не позволяют корректно определить равенство или различие, если один из операндов содержит 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 | #практика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 | #практика• работу с Linux и командной строкой • Git и контроль версий в реальных проектах • создание Docker-образов и запуск контейнеров • автоматизацию сборки, тестирования и деплоя в GitLab CI/CD • развёртывание и управление приложениями в Kubernetes • сети, хранилища, конфигурации и секреты • диагностику инфраструктуры и автоматизацию рутинных задач ... и многое другоеВсе знания закрепляются на практике с помощью заданий с автопроверкой. Материал подаётся последовательно и понятным языком: с примерами, схемами и демонстрациями. Во время обучения можно задавать вопросы по урокам и заданиям, получать обратную связь и помощь при возникновении сложностей. После прохождения программы вы получите сертификат, который можно добавить в резюме. Скидка 20% на 48 часов: по промокоду
READY20 стоимость всей программы составит 10 392 ₽.
Открыть программу на Stepikgroupby() в Pandas и Polars выполняет роль GROUP BY в SQL, merge() аналогичен JOIN, sort_values() заменяет ORDER BY, а unique() работает как SELECT DISTINCT.
На картинке — основные операции для работы с таблицами: загрузка данных, просмотр строк, фильтрация, сортировка, группировка, объединение таблиц, переименование и удаление колонок в Pandas, Polars и SQL.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс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 | #советДобавить колонку, переименовать её, изменить тип или задать ограничение — всё это делается через ALTER TABLE. Один из важнейших инструментов в работе с готовыми таблицами.
➡️ SQL Ready | #шпораWHERE применяется функция к полю, оптимизатор часто не может использовать обычный индекс.
Таблица:
users(id, email)
Создадим индекс на email:
CREATE INDEX idx_users_email
ON users(email);
Теперь простой поиск по точному значению использует этот индекс:
SELECT *
FROM users
WHERE email = 'test@mail.com';
Но в реальных проектах часто нужна нормализация данных. Например, искать email без учёта регистра через LOWER():
SELECT *
FROM users
WHERE LOWER(email) = 'test@mail.com';
Проблема в том, что PostgreSQL должен применить LOWER() к каждой строке, а потом сравнить результат. Обычный индекс по email для такого условия уже не подходит.
Решение — создать индекс не на колонку, а на результат выражения:
CREATE INDEX idx_users_lower_email
ON users(LOWER(email));
Теперь база хранит вычисленные значения в индексе и может быстро находить совпадения:
EXPLAIN ANALYZE
SELECT *
FROM users
WHERE LOWER(email) = 'test@mail.com';
Та же техника работает и для других преобразований. Например, если часто ищем заказы по году создания:
CREATE INDEX idx_orders_year
ON orders(EXTRACT(YEAR FROM created_at));
Теперь запросы по этому выражению могут использовать индекс вместо полного прохода таблицы.
Индекс нужно создавать под реальные запросы. Лишние увеличивают время INSERT/UPDATE и занимают место.
🔥 Индексы по выражениям полезны, когда одно и то же вычисление постоянно используется в WHERE, JOIN или ORDER BY.
➡️ SQL Ready | #практика• Рассматриваются возможности PostgreSQL, которые помогают решать типовые backend-задачи на уровне базы;
• Разбираются эффективные инструменты для работы с очередями, запросами, индексами и поиском;
• Показывается, как использовать встроенные механизмы PostgreSQL для повышения производительности приложений.
🔊 Продолжайте читать на Habr!
➡️ SQL Ready | #статьяINNER JOIN возвращает только совпадающие записи, LEFT/RIGHT JOIN сохраняют данные одной из сторон, а FULL JOIN объединяет полный набор данных из обеих таблиц. Дополнительные проверки через NULL позволяют находить отсутствующие связи между сущностями.
На картинке — основные типы JOIN и визуальное представление того, какие строки попадут в результат выполнения запроса.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс