SQL Portal | Базы Данных
14.5K subscribers
582 photos
78 videos
41 files
491 links
Присоединяйтесь к нашему каналу и погрузитесь в мир баз данных

Связь: @devmangx

РКН: https://clck.ru/3H4Wo3
Download Telegram
Пользователи часто хотят получать отчёты из базы данных, адаптированные под их нужды; запросы на такую кастомизацию могут со временем превратить систему в нечто вроде

SQL-инъекции как сервис


Товарищ рассказывает историю одной такой системы, где в итоге один из пользователей удалил критичные данные:

https://idiallo.com/blog/sql-injection-as-a-feature

Берегите свои данные, коллеги! 🐒

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍1🔥1
Подготовленные выражения / параметризованные запросы в Postgres

Подготовленные выражения — это повторно используемые SQL-запросы, которые позволяют обойти стадию планирования, повторно используя уже построенный план выполнения и подставляя разные данные.

Полноценный SQL-запрос в Postgres проходит через следующие этапы:

- Парсинг — преобразование в внутреннее представление;
- Переписывание / трансформация — применение правил переписывания запроса, создание внутренних представлений (например, CTE или view);
- Планирование — планировщик Postgres использует статистику по таблицам и другую информацию, чтобы выбрать оптимальный план выполнения;
- Выполнение — непосредственный запуск запроса.

Подготовленные выражения используют тот же SQL и сохраняют первые три шага. Это значит, что при выполнении остаётся только извлечь данные — Postgres может полностью пропустить стадию планирования.

Пример

Подготовить запрос и сохранить план выполнения

PREPARE get_user_by_email (text) AS
SELECT * FROM users WHERE email = $1;


Выполнить с одним параметром

EXECUTE get_user_by_email('alice@test.com');


Выполнить с другим параметром

EXECUTE get_user_by_email('bob@test.com');


Освободить ресурсы

DEALLOCATE get_user_by_email;


ORM'ы часто работают с подготовленными выражениями, и это может значительно повысить производительность приложений. Со стороны приложения такие запросы обычно называют параметризованными. Параметризованный запрос содержит плейсхолдеры, которые заполняются значениями позже. Такой запрос на стороне БД превращается в подготовленное выражение.

Примеры в коде

В Rails:

User.where("email = ?", "alice@test.com")


В Python:

cur.execute("SELECT * FROM users WHERE email = %s", ("alice@test.com",))


👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍1🔥1
Изучаем базы данных

Дорожная карта, которая поможет глубже разобраться в мире СУБД

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
Новичок в использовании pg_stat_statements для анализа производительности запросов в Postgres?

Попробуй этот простой веб-учебник:
https://crunchydata.com/developers/playground/query-performance-analytics

💡Там есть пара отличных запросов, которые стоит сохранить для дальнейшего использования.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Новая фича в PostgreSQL 17 — геймчейнджер

Эта новая возможность в PostgreSQL 17 настоящая революция.

🔸Механика страниц в PostgreSQL

PostgreSQL, как и большинство СУБД, работает с страницами фиксированного размера.
Практически всё — таблицы, индексы и т.д. хранится в виде страниц размером 8 КБ.

Каждая страница содержит:
- строки таблицы или кортежи индекса
- фиксированный заголовок

Страницы это просто байты в файлах. Они читаются и кэшируются в буферном пуле

Примеры чтения страниц:
- Страница 0: read(offset=0, size=8192)
- Страница 1: read(offset=8193, size=8192)
- Страница 7: read(offset=57345, size=8192)

Если таблица занимает 100 страниц, то для full table scan придётся выполнить 100 системных вызовов.
А каждый системный вызов имеет накладные расходы.

🔸Что изменилось в Postgres 17

Добавили возможность объединения I/O:
- Можно указать, сколько страниц читать за один системный вызов
- Теоретически можно просканировать всю таблицу за один системный вызов

Это не всегда хорошая идея, подробнее об этом ниже.

Также добавили поддержку векторизованного I/O:
- Используется системный вызов preadv
- Он принимает массив оффсетов и длин — удобно для произвольного чтения

🔸Проблема: не читать лишнего

Допустим, мы делаем seq scan, чтобы найти значение:
1. Читаем страницу 0
2. Находим нужное → выходим
3. Остальные страницы не нужны

Теперь с новой фичей:
- Мы читаем сразу 10 страниц одним I/O
- Загружаем всё в shared buffers
- А нужное было уже на первой странице

> Результат — потрачены ресурсы (диск, память) впустую

🔸Как это сбалансировать

Нужно будет находить баланс:
- Между эффективным I/O
- И избежанием избыточного чтения

🔸Примечание

PostgreSQL действительно вызывает системный вызов ядра, чтобы читать по 8 КБ за раз.
Но ядро может быть настроено на read-ahead — заранее читать больше и кэшировать это в файловом кэше ОС.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍64
Media is too big
VIEW IN TELEGRAM
Интерактивная тренировка SQL

Если хочешь прокачать SQL на практике без установки СУБД и настройки окружения заходи на sqltest.online

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥5🌭3
Amazon Aurora стала первой OLTP базой данных, которая популяризировала разделение хранения данных и вычислительных ресурсов.

Главным новшеством стала переработка слоя хранения с целью минимизировать операции записи (write I/O) для преодоления задержек, связанных с сетью.

Как бы круто это ни было, она всё же не может превзойти локальные NVMe SSD.

Ссылка на статью:
https://pages.cs.wisc.edu/~yxy/cs764-f20/papers/aurora-sigmod-17.pdf

На видео показана PlanetScale Metal на AWS против Aurora. Те же CPU и объем памяти при I/O-насыщенной нагрузке, похожей на TPCC.

Значительно выше QPS при при этом в 3 раза ниже p99 задержка

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
6
This media is not supported in your browser
VIEW IN TELEGRAM
База данных имеет право выполнять части SQL-выражения WHERE в любом порядке.

Так как же избежать ошибок, если известно, что выражение может выбросить ошибку,

например, извлечение квадратного корня из отрицательного числа?

Используй CASE, чтобы выполнять вычисление только для допустимых значений:

WHERE CASE 
WHEN col > 0 THEN SQRT(col)
ELSE ...
END ...


👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍86🔥4
JSON-реляционные duality views в Oracle Database 23ai — это гибкий, производительный и согласованный способ доступа к данным как:

- документам,
- реляционным таблицам,
- и к обоим одновременно 💊

anders__swanson показывает, как создать базовые duality views для этого.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
6
6 структур данных для экономии места в базе данных

Фильтр Блума
Снижает стоимость поиска, проверяя, является ли элемент членом множества.

HyperLogLog
Оценивает количество уникальных элементов.

Cuckoo filter
Проверяет, принадлежит ли элемент множеству.

Minhash
Находит сходство между множествами.

SkipList
Эффективно ищет, вставляет и удаляет элементы из отсортированного списка.

Count-min sketch
Находит частоту элементов в большом потоке данных.


👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
5
This media is not supported in your browser
VIEW IN TELEGRAM
Если ты хочешь изучить SQL или погрузиться в аналитику, начинай с Mode SQL Tutorial. У них всё работает прямо в браузере - никаких заморочек с установкой СУБД.

Что тебя ждёт:

— Basic SQL — SELECT, WHERE, ORDER BY, LIMIT и логические операторы;
— Intermediate SQL — агрегаты, GROUP BY, HAVING, JOINы;
— Advanced SQL — window functions, подзапросы, pivot’ы и performance-tuning;
— SQL Analytics Training — реальные кейсы аналитики, включая A/B тестирование и инсайты продукта.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
4
Партиционирование таблиц в Postgres — это только для огромных таблиц? Вовсе нет.

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

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

Партиционирование помогает:

- Ускорить запросы — Postgres ищет только в нужном партиционе, а не во всей таблице
- Снизить блокировки, нагрузку на WAL и CPU во время обслуживания
- Упростить и структурировать архивирование

Пример

Представим, что у вас есть таблица с 500K заказов.
Если просто сделать DELETE за Q1 2023:

- блокируются строки на несколько секунд
- создаётся большое количество WAL
- место освобождается не сразу

Возможно, придётся выполнять такую очистку вне продакшн-часов, чтобы не мешать работе приложения.

Но если таблица партиционирована по дате, вы можете:

- архивировать данные
- удалить нужную партицию (DROP TABLE ...)

Это не затронет активные данные и сразу освободит место.

Думаете, для партиционирования придётся переписывать приложение?

Обычно — нет.

Большинство приложений и ORM:

- работают с прозрачным партиционированием без проблем
- видят всё как одну таблицу
- а Postgres сам направляет запросы в нужные партиции

Всё работает без изменений в коде.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍65
Что такое pg_partman и что он добавляет к встроенному в Postgres партиционированию?

В Postgres из коробки есть нативное партиционирование:
- Декларативный синтаксис партиционирования в CREATE TABLE
- Автоматическое отсечение партиций (partition pruning), когда запросы исключают нерелевантные партиции
- Прозрачные DML-операции — INSERT/UPDATE/DELETE работают по всем партициям без дополнительной обработки

Что добавляет pg_partman:
- Автоматически создаёт новые партиции по расписанию
- Автоматически удаляет старые партиции по времени или количественным правилам
- Фоновый воркер для выполнения обслуживания без внешних заданий

https://github.com/pgpartman/pg_partman

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥43👍3
Postgres DOMAINs… лучше, чем CONSTRAINTs?

DOMAIN позволяет задать конкретную проверку значений.

Например, если я хочу убедиться, что все даты рождения больше 1 января 1930 года, а все email-адреса валидны, я могу создать вот так:

CREATE DOMAIN date_of_birth AS date
CHECK (value > '1930-01-01'::date)
;

CREATE DOMAIN valid_email AS text
NOT NULL
CHECK (value ~* '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$')
;


При создании таблицы достаточно назначить типы date_of_birth и valid_email соответствующим колонкам.

Если в базе есть несколько полей, хранящих дату рождения или email, логика для этих полей будет переиспользована и для дополнительных колонок.

CREATE TABLE person_using_domains
(
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
firstname TEXT NOT NULL,
lastname TEXT NOT NULL,
birth_date date_of_birth,
email valid_email
);


🤔 DOMAIN vs CHECK CONSTRAINT

Может возникнуть вопрос - зачем использовать DOMAIN, если можно просто навесить CHECK constraint прямо на колонку?
Простой ответ: CHECK constraints не так просто изменять — их нужно удалять и создавать заново.

Кроме того, DOMAIN можно создать на уровне схемы, и если в нескольких таблицах есть колонки с email или датой рождения, можно использовать один DOMAIN для управления всеми этими полями, тем самым централизуя логику.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4
Бросок кубика определяет исход атаки в D&D.

Поэтому знание распределения результатов бросков помогает выбрать правильное действие.

При этом нужно учитывать преимущество , помеху и удачу.

Sean D. Stuber показывает, как сделать это в Oracle SQL.

https://seanstuber.com/2025/07/29/using-sql-to-derive-dice-distributions-in-dnd/

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
2