Например,
ROUND() используется для округления значений, MOD() — для получения остатка от деления, а агрегатные функции AVG(), SUM(), MIN() и MAX() помогают выполнять вычисления по наборам данных.На изображении собраны основные числовые функции: назначение, синтаксис, примеры запросов и особенности использования в разных СУБД.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🔥8🤝3👍2
This media is not supported in your browser
VIEW IN TELEGRAM
В репозитории собраны материалы для изучения работы с базами данных: от основ SQL и проектирования таблиц до функций, индексов, транзакций, оконных функций, PL/pgSQL и продвинутых возможностей PostgreSQL. Отличный вариант, чтобы разобраться с базами данных и перейти от простых запросов к пониманию работы СУБД.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤6🔥5🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
Онлайн-учебник для изучения SQL: от базовых запросов до более сложной работы с данными. Теория сопровождается примерами и упражнениями, поэтому изученные конструкции можно сразу закреплять на практике. Материал разделён на главы, что удобно для поэтапного обучения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17👍7🤝3🔥2
Настройте оценку пользовательских функций!
Для пользовательской функции PostgreSQL позволяет явно указать стоимость вызова через
Причём пересоздавать функцию не обязательно:
Чем выше
PostgreSQL прямо предоставляет
🔥 Если пользовательская функция ломает оценки строк или вызывается слишком часто, проверьте
➡️ SQL Ready | #совет
Для пользовательской функции PostgreSQL позволяет явно указать стоимость вызова через
COST, а для функции, возвращающей набор строк, — ожидаемое число строк через ROWS. Причём пересоздавать функцию не обязательно:
ALTER FUNCTION find_orders(bigint)
ROWS 5;
ALTER FUNCTION expensive_check(jsonb)
COST 500;
Чем выше
COST, тем дороже планировщик считает вычисление и тем сильнее старается не выполнять его лишний раз. PostgreSQL прямо предоставляет
COST и ROWS как информацию для оптимизации пользовательских функций. EXPLAIN (ANALYZE, BUFFERS)
SELECT u.id, o.*
FROM users u
CROSS JOIN LATERAL find_orders(u.id) o;
COST и ROWS — иногда правильный план получается без переписывания запроса и новых индексов.Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍8🔥4
Проверяйте JSON без преобразования!
Если JSON приходит как
Можно сразу потребовать конкретный тип
Есть и более интересная проверка — запрет повторяющихся ключей:
Это можно использовать непосредственно в ограничении таблицы:
🔥
➡️ SQL Ready | #совет
Если JSON приходит как
text, необязательно делать ::jsonb и ловить ошибку преобразования. IS JSON просто вернёт true или false.SELECT '{"id": 42}' IS JSON; -- true
SELECT '{broken}' IS JSON; -- falseМожно сразу потребовать конкретный тип
JSON:SELECT payload IS JSON OBJECT
FROM staging;
SELECT payload IS JSON ARRAY
FROM staging;
Есть и более интересная проверка — запрет повторяющихся ключей:
SELECT '{"id":1,"id":2}'
IS JSON OBJECT WITH UNIQUE KEYS;
-- falseЭто можно использовать непосредственно в ограничении таблицы:
CREATE TABLE incoming_events (
payload text NOT NULL
CHECK (payload IS JSON OBJECT WITH UNIQUE KEYS)
);
IS JSON позволяет валидировать JSON как обычное условие SQL — без преобразований, исключений и регулярных выражений.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍5🤝3❤1
COUNT(*) в PostgreSQL: MVCC, visibility map и стоимость выполнения!
В PostgreSQL точный
На большой таблице планировщик часто выбирает
Наличие
Однако
PostgreSQL оптимизирует эту проверку с помощью visibility map. Если страница отмечена как
После изменения страницы её флаг
Поэтому на активно изменяемых таблицах даже
Таким образом, производительность
Если транзакционно точное количество строк не требуется, можно использовать статистическую оценку из
🔥 Для больших таблиц это принципиально разные варианты: полный MVCC-корректный подсчёт или быстрое получение приблизительной статистической оценки.
➡️ SQL Ready | #практика
В PostgreSQL точный
COUNT(*) требует определить количество строк, видимых текущему MVCC snapshot. Глобального счётчика, который можно было бы использовать для транзакционно корректного результата, у таблицы нет:SELECT COUNT(*)
FROM orders;
На большой таблице планировщик часто выбирает
Seq Scan, поскольку для точного результата всё равно требуется обработать множество видимых строк:Aggregate
-> Seq Scan on orders
Наличие
PRIMARY KEY или другого подходящего индекса не гарантирует его использование. Если модель стоимости считает путь через индекс дешевле, PostgreSQL может выполнить запрос через Index Only Scan:Aggregate
-> Index Only Scan using orders_pkey on orders
Однако
Index Only Scan не означает получение готового количества записей из индекса. Информация, необходимая для определения MVCC-видимости строк, находится в heap, а не в самом индексе.PostgreSQL оптимизирует эту проверку с помощью visibility map. Если страница отмечена как
all-visible, PostgreSQL может считать находящиеся на ней строки видимыми без дополнительного обращения к heap:EXPLAIN (ANALYZE, BUFFERS)
SELECT COUNT(*)
FROM orders;
После изменения страницы её флаг
all-visible сбрасывается и впоследствии может быть снова установлен VACUUM.Поэтому на активно изменяемых таблицах даже
Index Only Scan может требовать дополнительных обращений к heap:Index Only Scan using orders_pkey on orders
Heap Fetches: 18427
Таким образом, производительность
COUNT(*) зависит не только от размера таблицы и наличия индекса, но и от состояния visibility map, характера нагрузки, работы autovacuum, выбранного плана выполнения и состояния кэша PostgreSQL.Если транзакционно точное количество строк не требуется, можно использовать статистическую оценку из
pg_class:SELECT reltuples::bigint
FROM pg_class
WHERE oid = 'orders'::regclass;
reltuples обновляется, в частности, при VACUUM и ANALYZE и остаётся приблизительной оценкой. Если статистика для таблицы ещё не собиралась, значение может быть -1.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍6🤝5❤2
This media is not supported in your browser
VIEW IN TELEGRAM
Материалы посвящены не написанию SQL-запросов, а архитектуре СУБД и внутренним механизмам обработки и хранения данных. Подробно рассматриваются физическая структура базы данных, системные каталоги, управление транзакциями, блокировки, WAL и др.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍9❤3🤝1
Проверяйте связи с учётом периода!
В PostgreSQL 18 связь может учитывать ещё и период его действия.
А теперь интересная часть:
Период скидки должен быть покрыт соответствующими периодами родительской таблицы. Причём покрытие может обеспечиваться несколькими соседними строками, а не обязательно одной.
Например, такую логику больше не обязательно проверять вручную перед записью:
🔥 В PostgreSQL 18
➡️ SQL Ready | #совет
В PostgreSQL 18 связь может учитывать ещё и период его действия.
WITHOUT OVERLAPS не даст создать пересекающиеся периоды для одного product_id. По сути PostgreSQL сам обеспечивает проверку пересечения диапазонов. А теперь интересная часть:
CREATE TABLE discounts (
product_id bigint,
valid_at daterange,
FOREIGN KEY (
product_id,
PERIOD valid_at
)
REFERENCES prices (
product_id,
PERIOD valid_at
)
);
Период скидки должен быть покрыт соответствующими периодами родительской таблицы. Причём покрытие может обеспечиваться несколькими соседними строками, а не обязательно одной.
Например, такую логику больше не обязательно проверять вручную перед записью:
INSERT INTO discounts
VALUES (
42,
'[2026-05-01,2026-05-15)'::daterange
);
PERIOD позволяет проверять временные связи обычным FOREIGN KEY — без триггеров и ручных проверок.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤9🔥6
Например, Replication повышает доступность и отказоустойчивость за счёт хранения копий данных на нескольких узлах, а Sharding позволяет горизонтально масштабировать систему, распределяя данные между независимыми шардами.
Эти паттерны помогают решать основные задачи распределённых систем: масштабирование, отказоустойчивость, распределение данных, асинхронное взаимодействие и согласованность.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍7🤝5❤3
Почему UNIQUE допускает несколько NULL в PostgreSQL!
Ограничение
Повторное определённое значение
При использовании
Особенно важно учитывать это поведение в составных ключах, где один из столбцов может быть неопределённым:
Одинаковые определённые значения
Начиная с PostgreSQL 15 это поведение можно изменить через
Теперь сохранить две строки с одной комбинацией
Та же семантика поддерживается уникальными индексами, поэтому правило можно выразить непосредственно на уровне индекса.
В такой таблице может существовать одна строка с
🔥
➡️ SQL Ready | #практика
Ограничение
UNIQUE гарантирует уникальность значений, но для NULL в PostgreSQL действует отдельная семантика. По умолчанию два NULL считаются различными при проверке уникальности, поэтому ограничение не запрещает несколько строк с неопределённым значением:CREATE TABLE users (
id BIGINT PRIMARY KEY,
email TEXT UNIQUE
);
Повторное определённое значение
email нарушит ограничение уникальности.INSERT INTO users (id, email)
VALUES (1, 'user@example.com');
INSERT INTO users (id, email)
VALUES (2, 'user@example.com');
При использовании
NULL те же правила не применяются: несколько строк успешно проходят проверку ограничения.INSERT INTO users (id, email)
VALUES
(3, NULL),
(4, NULL),
(5, NULL);
Особенно важно учитывать это поведение в составных ключах, где один из столбцов может быть неопределённым:
CREATE TABLE contacts (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE (company_id, external_id)
);
Одинаковые определённые значения
(company_id, external_id) конфликтуют, но несколько комбинаций (10, NULL) по умолчанию допустимы:INSERT INTO contacts (id, company_id, external_id)
VALUES
(1, 10, NULL),
(2, 10, NULL);
Начиная с PostgreSQL 15 это поведение можно изменить через
NULLS NOT DISTINCT. В таком ограничении NULL считаются неразличимыми при проверке уникальности:CREATE TABLE contacts_strict (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (company_id, external_id)
);
Теперь сохранить две строки с одной комбинацией
(10, NULL) нельзя: вторая вставка завершится нарушением уникальности.INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (1, 10, NULL);
INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (2, 10, NULL);
Та же семантика поддерживается уникальными индексами, поэтому правило можно выразить непосредственно на уровне индекса.
CREATE UNIQUE INDEX uq_contacts_company_external
ON contacts (company_id, external_id)
NULLS NOT DISTINCT;
NULLS NOT DISTINCT не эквивалентен NOT NULL. NOT NULL полностью запрещает отсутствие значения, тогда как NULLS NOT DISTINCT разрешает NULL, но включает его в контроль уникальности.CREATE TABLE identifiers (
id BIGINT PRIMARY KEY,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (external_id)
);
В такой таблице может существовать одна строка с
external_id IS NULL, но вторая аналогичная строка уже нарушит ограничение.UNIQUE в PostgreSQL по умолчанию допускает несколько NULL. Если отсутствие значения также должно быть уникальным состоянием, начиная с PostgreSQL 15 это можно явно зафиксировать через NULLS NOT DISTINCT.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍6🤝5❤1
This media is not supported in your browser
VIEW IN TELEGRAM
Материал ведёт от первых SQL-запросов и проектирования схем до индексов, транзакций, оптимизации и работы с БД из Python через SQLAlchemy и Alembic. Особенно полезно, что SQLite и PostgreSQL изучаются параллельно: автор показывает различия между ними, типичные ошибки и ситуации, где выбор СУБД имеет значение.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤9🔥4🤝2