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

Связь: @devmangx

РКН: https://clck.ru/3H4Wo3
Download Telegram
Производительность PostGIS: предикаты пересечения и оверлеи. Новая статья от Пола Рэмзи.

В чём разница между булевыми ST_Intersects и ST_Contains и операциями оверлея ST_Intersection и ST_Difference?

Сегодня разберем самые эффективные подходы к выборке объектов внутри других объектов.

Обычно мелкие геометрии обрезаются по границе с помощью ST_Intersection.

Наивный SQL — это обычный spatial join по ST_Intersects:

SELECT ST_Intersection(polygon.geom, p.geom) AS geom
FROM parcels p
JOIN polygon
ON ST_Intersects(polygon.geom, p.geom);


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

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

Что это значит?

Булевые пространственные предикаты - это функции вроде ST_Intersects и ST_Contains. Они принимают две геометрии и возвращают true/false в зависимости от результата проверки.

Операции пространственного оверлея . вроде ST_Intersection или ST_Difference - получают две геометрии и генерируют новую.

Предикаты быстрее, потому что могут прерывать проверку заранее (например, если найдены пересекающиеся ребра, значит геометрии пересекаются) и потому что используют оптимизации prepared geometry с кешированием структуры ребер.

Ускорение работы с оверлеями основано на простой идее = многие объекты вообще не нужно клиппать, если они полностью внутри полигональной границы. Их можно определить с помощью ST_Contains.

Есть и меньшая группа объектов, которые пересекают границу, их уже нужно обрабатывать через ST_Intersection — те, что ST_Intersects, но не ST_Contains.

Более быстрый запрос использует предикаты, чтобы разделить объекты на две категории: полностью внутри (оставляем как есть) и пересекающие границу (клиппим).

SELECT
CASE
WHEN ST_Contains(polygon.geom, p.geom) THEN p.geom
ELSE ST_Intersection(polygon.geom, p.geom)
END AS geom
FROM parcels p
JOIN polygon
ON ST_Intersects(polygon.geom, p.geom);


Здесь используются два предиката:

– ST_Intersects в join выбирает только кандидатов для обработки
– ST_Contains внутри CASE пропускает геометрии, которые не нужно клиппить

На том же тестовом наборе запрос выполняется примерно за 9 мс - разница настолько заметна, что её видно даже на маленьком примере.

Суть подхода: комбинируем предикаты и оверлеи через CASE


Главная идея = булевые пространственные проверки (ST_Contains, ST_Intersects) значительно дешевле, чем операции вроде ST_Intersection. Обычный подход клиппит все пересекающиеся геометрии. Оптимизированный вариант использует CASE и ST_Contains, чтобы сделать shortcut: если объект полностью внутри. то просто возвращаем его без изменений и не вызываем дорогой ST_Intersection.

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

Разделяя данные на два потока — «полностью внутри» (быстрый путь) и «пересекает» (медленный путь), мы гарантируем, что дорогостоящая геометрическая обработка выполняется только там, где она реально нужна.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2
Вопрос по SQL:

Какой результат вернёт этот запрос?

Посмотрим, кто хорошо знает агрегатные функции.

Объясни свой ответ.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍74
This media is not supported in your browser
VIEW IN TELEGRAM
Появилась интересная новинка для тех, кто постоянно работает с данными и устал писать SQL вручную. Вышел OpenChatBI — опенсорсный BI инструмент, который позволяет делать запросы к базе обычным языком и получать результат в виде таблиц или графиков.

Инструмент построен на LangGraph и LangChain, умеет превращать текстовые запросы в SQL и автоматически их выполнять. Для сложных вопросов можно подключить внешние источники знаний или расширить функциональность через MCP.

У OpenChatBI есть удобный Web UI, а установка занимает пару минут — достаточно поставить через pip или uv, подключить базу и настроить LLM.

Репозиторий здесь: https://github.com/zhongyu09/openchatbi

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍2🤔1
Типичные проблемы при очистке данных в SQL и как их решать

Удаление дубликатов
├── Использование DISTINCT
└── Использование ROW_NUMBER()

Обработка пропущенных значений
├── Фильтрация NULL
└── Замена NULL

Стандартизация данных
├── Приведение типов
└── Форматирование данных

Удаление выбросов
├── Фильтрация по условиям
└── Применение статистических методов

Исправление опечаток
├── Использование UPDATE
└── Использование CASE

Нормализация данных
├── Создание lookup-таблиц
└── Разделение колонок

Обработка разнородных данных
├── Использование CASE WHEN
└── Использование REPLACE

Парсинг данных
├── Использование SUBSTRING
└── Использование CHARINDEX


👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63
Мои топ-5 советов по оптимизации Postgres для разработчиков:

- научись пользоваться EXPLAIN. Он покажет, как именно выполняется запрос и где его можно подтюнить.

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

- используй connection pooling. В Postgres его нет из коробки, и для каждого подключения поднимается отдельный процесс. Используй серверный или клиентский пул, а лучше оба. Просто используй что-то.

- запрашивай только то, что надо. Избегай SELECT * FROM. Будь точнее SELECT column1, column2 FROM. Не трать ресурсы на данные, которые твоему приложению не нужны.

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

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥1
В Postgres есть функция age(), которая позволяет быстро получить возраст по timestamp.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍4🔥4👀1
В PL/SQL

EXCEPTION WHEN OTHERS THEN


Ловит любые ошибки

Если пихать это везде и не пробрасывать ошибку дальше, можно спокойно пропустить неожиданные проблемы

Поэтому компилятор кидает предупреждение PLW-6009

Если в кастомном логгере ты все-таки пробрасываешь ошибку дальше, то используй

PRAGMA SUPPRESSES_WARNING_6009


чтобы отключить это предупреждение

ALTER SESSION SET PLSQL_WARNINGS='ENABLE:(6009)';

CREATE PROCEDURE logging ( err VARCHAR2 ) AS
PRAGMA SUPPRESSES_WARNING_6009(logging);
BEGIN
-- логирование ошибки / повторный RAISE
END;
/

CREATE PROCEDURE do_stuff AS
BEGIN
-- какая-то логика
EXCEPTION
WHEN OTHERS THEN logging('Error details');
END;
/

-- Нет ошибок.


👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥51
В Postgres есть десятки типов индексов, заточенных под разные типы данных и задачи. В целом их можно разделить на две категории:

По назначению или области применения (что именно индексируем). Здесь мы решаем, какие колонки или данные таблицы индексировать и нужно ли применять функцию к индексируемым значениям. Примеры: индекс по одной колонке, составной (composite), покрывающий (covering), частичный (partial) и функциональный/выражения (functional/expression) индекс.

По внутренней структуре и методу доступа (как индексируем). Эта категория основана на том, как индекс хранит данные под капотом и как СУБД к ним обращается. Примеры: B-tree, hash, GIN, RUM, GiST, SP-GiST, BRIN, HNSW и IVFFlat.

Когда ты выполняешь CREATE INDEX, ты всегда выбираешь тип индекса из первой категории (что индексировать). Выбор структуры (как индексировать) — опционален. Если ничего не указать, Postgres по умолчанию использует B-tree.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
6
Postgres UNION vs UNION ALL

Оба оператора объединяют результаты двух или более SELECT запросов в один набор данных.

UNION удаляет дубликаты

UNION ALL оставляет дубликаты

Если ты уверен что дубликатов нет или они тебя не волнуют, UNION ALL будет быстрее, потому что пропускает проверку на повторяющиеся строки.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👀2🔥1
Мы уже знаем причину худшего сбоя Cloudflare с 2019 года — криво спроектированный SQL-запрос.

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

Внутренний файл разросся до безумных размеров, уронил тысячи серверов и положил половину интернета.

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

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7👍2
Postgres использует TOAST для хранения больших переменных значений вроде JSONB и TEXT.

Использование TOAST влияет на производительность, так что нужно понимать компромиссы.

Каждая строка хранится в файле, который разбит на страницы по 8 KB. Обычно одна страница может держать десятки или сотни строк, но это зависит от количества и типов колонок.

Широкие таблицы могут иметь строки размером в несколько килобайт. Если строка превышает порог (например, около 2 KB), Postgres решает использовать The Oversized-Attribute Storage Technique (TOAST), а не запихивать все данные в основной файл таблицы.

TOAST применяет сжатие и перенос больших значений в отдельную таблицу — TOAST-таблицу. У нее всего три колонки: chunk_id, chunk_seq и chunk_data. Большие значения режутся на чанки, эти чанки кладутся в отдельную таблицу, а в основной таблице остается только ссылка на них.

Это позволяет держать строки в основном файле компактными. Минус в том, что при обращении к таким данным нужно делать дополнительные I/O на другую таблицу (и возможно тратить CPU на декомпрессию). Гибкость в работе с большими полями удобна, но может ударить по перформансу по сравнению с хранением всего в основной таблице или нормализацией данных в компактные фиксированные колонки.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
❤️ В статье на Хабре Андрей Колнооченко, бэкенд‑разработчик в Яндекс 360, делится опытом масштабной миграции данных из MongoDB в PostgreSQL в Яндекс Диске:

• Как переносили сотни миллионов записей без даунтайма и потерь;
• Почему отказались от распределённых транзакций и как обеспечили согласованность данных;
• Как выкатывали изменения поэтапно — с возможностью отката в любой момент.

Всё это — под высокой нагрузкой, без влияния на пользователей и с полной гарантией доступности сервиса.

↘️ Читайте на Хабре!
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Forwarded from IT Portal
This media is not supported in your browser
VIEW IN TELEGRAM
Дружеское напоминание: у PostgreSQL есть официальное расширение для VS Code

Оно заметно упрощает работу с Postgres и позволяет взаимодействовать с базой данных прямо в редакторе

Основные плюшки:
- Встроенная визуализация схемы БД
- Общаться с базой данных через агентов
- Смотреть метрики и аналитику
- Быстрый запуск PostgreSQL в Docker
- IntelliSense с контекстом БД (автокомплит, форматирование, подсветка синтаксиса)
…и многое другое


Ссылка на расширение: PostgreSQL for VS Code

@IT_Portal
5👍3