SQL Portal | Базы Данных
14.6K subscribers
825 photos
111 videos
44 files
648 links
Присоединяйтесь к нашему каналу и погрузитесь в мир баз данных

Связь: @devmangx

РКН: https://clck.ru/3H4Wo3
Download Telegram
OUTER JOIN или внешнее соединение позволяет возвратить все строки одной или двух таблиц, которые участвуют в соединении.

Outer Join имеет следующий формальный синтаксис:

SELECT столбцы
FROM таблица1
{LEFT|RIGHT|FULL} [OUTER] JOIN таблица2 ON условие1
[{LEFT|RIGHT|FULL} [OUTER] JOIN таблица3 ON условие2]...


Перед оператором JOIN указывается одно из ключевых слов LEFT, RIGHT или FULL, которые определяют тип соединения:

LEFT: выборка будет содержать все строки из первой или левой таблицы

RIGHT: выборка будет содержать все строки из второй или правой таблицы

FULL: выборка будет содержать все строки из обеих таблиц

Перед оператором JOIN может указываться ключевое слово OUTER, но его применение необязательно. После JOIN указывается присоединяемая таблица, а затем идет условие соединения после оператора ON.

К примеру, возьмем следующие таблицы:

CREATE TABLE Products
(
Id SERIAL PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Company VARCHAR(20) NOT NULL,
ProductCount INTEGER DEFAULT 0,
Price NUMERIC NOT NULL
);
CREATE TABLE Customers
(
Id SERIAL PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL
);
CREATE TABLE Orders
(
Id SERIAL PRIMARY KEY,
ProductId INTEGER NOT NULL REFERENCES Products(Id) ON DELETE CASCADE,
CustomerId INTEGER NOT NULL REFERENCES Customers(Id) ON DELETE CASCADE,
CreatedAt DATE NOT NULL,
ProductCount INTEGER DEFAULT 1,
Price NUMERIC NOT NULL
);


И соединим таблицы Orders и Customers:

SELECT FirstName, CreatedAt, ProductCount, Price, ProductId 
FROM Orders LEFT JOIN Customers
ON Orders.CustomerId = Customers.Id;


Таблица Orders является первой или левой таблицей, а таблица Customers - правой таблицей. Поэтому, так как здесь используется выборка по левой таблице, то вначале будут выбираться все строки из Orders, а затем к ним по условию Orders.CustomerId = Customers.Id будут добавляться связанные строки из Customers.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
JSON types in Postgres

json

* текст
* без дубликатов ключей
* не индексируется
* парсится во время выполнения, поэтому медленнее

jsonb

* бинарный формат, заранее распарсен
* без дубликатов ключей
* индексируется
* лучше по производительности запросов

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍54
psql-лайфхак:

\e откроет твой дефолтный текстовый редактор, чтобы написать SQL или команды. Сохраняешь файл, закрываешь, и psql автоматически выполнит то, что ты написал.


🛌🛌🛌

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
2🤯2
MySQL 8.4.8 теперь доступен!

MySQL 8.4.8 (версия Long-Term Support, LTS) приносит несколько улучшений:

Улучшения InnoDB Redo Logging: сообщения об ошибках теперь включают текущий Log Sequence Number (LSN) и детали про емкость redo log, что дает более глубокое понимание работы redo log.
Встроенная библиотека OpenSSL обновлена до версии 3.0.18.
Как обычно, релиз закрывает разные баги, включая race conditions в InnoDB и проблемы с очисткой binary log (purging), чтобы улучшить общую стабильность и производительность.

Подробнее см. Release Notes

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42
В Postgres есть специальные операторы, которые делают запросы к JSON-данным простыми и быстрыми.

Базовые операторы:

-> извлечь как json
--> извлечь как текст
0, 1, 2 ... извлечь по смещению (offset)
@> левый операнд содержит правый
<@ правый операнд содержит левый
? ключ верхнего уровня

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

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

У некоторых есть небольшой перфоманс-трик: добавить GIN-индекс с jsonb_path_ops. Это вариант для схем JSON, которые не меняются, и работает он только с @> (contains). Зато может быть быстрее и занимать меньше места, чем обычный GIN-индекс.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Yandex B2B Tech запустили Managed Sharded PostgreSQL (SPQR) – сервис для горизонтального масштабирования самой популярной опенсорс БД в мире. Теперь банкам и ритейлу станет проще обрабатывать миллионы транзакций в реальном времени и без боли масштабировать свои системы по мере роста нагрузок.

В стандартном PostgreSQL горизонтального масштабирования нет, а при больших объёмах данных без него уже никуда. Шардированный PostgreSQL позволяет ускорять запуск новых продуктов в 3–4 раза, упрощает сопровождение и снижает операционные риски – инженерам не нужно вручную собирать и поддерживать сложную инфраструктуру.

Технология уже обкатана в проде – её используют Яндекс ID, Яндекс Пэй и Едадил, стабильность подтверждена и внешними компаниями. PostgreSQL сегодня выбирают 55,6% профессиональных разработчиков, а Managed Service for PostgreSQL в Yandex Cloud обслуживает уже больше 5 тысяч клиентов.

В итоге: быстрее time-to-market, меньше затрат на разработку при запуске высоконагруженных продуктов

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
6🤔3👍2
Alibaba выложили в опенсорс AliSQL (на базе MySQL 8.0.44) с встроенным движком DuckDB. Теперь аналитические нагрузки можно гонять прямо в MySQL — достаточно переключить storage engine на DuckDB.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Вчера мы говорили про GIN-индексы, но они не поддерживают ORDER BY. В некоторых ограниченных случаях можно использовать выраженные индексы на JSON-выборках, которые просто фиксируют текстовое значение по заданному keypath (пути к ключу).

CREATE INDEX idx_state
ON users ((details->'location'->>'state'));

{ "name": "David", "location": { "city": "Lawrence", "state": "KS" } }


➡️Не для общего случая, а под конкретные кейсы
➡️Ускоряют lookups по одиночным ключам в JSON
➡️B-tree индекс, поддерживает ORDER BY
➡️Убирает оверхед GIN или необходимость парсить JSON во время выполнения запроса

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
2
SELECT * FROM users LIMIT 100

SQL: "Не говори больше ничего, вот вся продакшен-база данных"

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁12🤔1
JSON, вставка данных.

Ты можешь изменять существующие JSONB-объекты с помощью функции jsonb_set(). Она возвращает новый JSONB-объект, где значение установлено по указанному пути ключей (keypath). Если по этому пути не хватает промежуточных объектов, она их создаст.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Колонарное хранилище vs построчное (row store) наглядно

Берем простую агрегацию и сравниваем, как она выполняется в row store и columnar store.

В row store данные лежат строками, поэтому движку приходится читать каждую строку целиком, чтобы из нее вытащить значение колонки age.

В columnar store данные лежат по колонкам, поэтому он читает сразу только значения колонки age, без трогания остальных полей и без лишнего I/O.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍3
Менеджер баз данных с редактором SQL и искусственным интеллектом: Dataflare

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3👍1🌚1
Радим Марек: Введение в буферы в PostgreSQL

Про то, как PostgreSQL держит данные в памяти и почему от этого сильно зависит производительность

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Media is too big
VIEW IN TELEGRAM
SQL tip:

Обновление значений в таблице через коррелированный подзапрос.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3
PostgreSQL по умолчанию не страхует тебя от забытых транзакций, idle-сессий и улетевших в бесконечность запросов: все это тихо накапливается, пока база не начинает казаться "залипшей".

Если мигрируешь на PostgreSQL, эти 5 параметров таймаутов критично настроить

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Индексация без простоя с CONCURRENTLY

Создание индекса может залочить таблицу, из-за чего она фактически становится недоступной и приложение/пользователи начинают получать ошибки.

Если добавить CONCURRENTLY, Postgres соберет индекс конкурентно, в фоне. Это займет чуть больше времени, зато пользователи вообще не заметят, что индекс строится.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В Postgres 18 появилась новая фича для ограничений по временным диапазонам: WITHOUT OVERLAPS. Это прям то, что нужно для систем бронирований, и в целом заметно проще, чем прошлые решения.

CREATE EXTENSION IF NOT EXISTS btree_gist;

CREATE TABLE staff_schedule (
staff_id int,
shift_duration tstzrange,
task_description text,
PRIMARY KEY (staff_id, shift_duration WITHOUT OVERLAPS)
);


- создаёт индекс, который комбинирует range и int
- не даёт добавлять дублирующиеся временные записи

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
8
Неиспользуемые индексы в PostgreSQL: риски, обнаружение и безопасное удаление

Индексы нужны, чтобы ускорять доступ к данным. Они позволяют PostgreSQL избегать full scan по таблице и заметно сокращают время выполнения запросов в read-heavy нагрузках.

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

Но индексы не бесплатны.

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

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

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

1.1. Медленнее INSERT, UPDATE и DELETE

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

1.2. Больше нагрузки на VACUUM и autovacuum

В индексах так же копятся мертвые tuple, как и в таблицах. Их тоже нужно вакуумить, из-за чего растут I/O и время работы vacuum.

1.3. Дольше окна обслуживания

Операции вроде VACUUM и REINDEX выполняются тем дольше, чем больше индексов и чем они крупнее.

1.4. Пустая трата диска и “засорение” кеша

Большие неиспользуемые индексы едят место на диске и могут вытеснять полезные данные из shared_buffers, снижая эффективность кеша.

Поэтому периодически находить и аккуратно удалять неиспользуемые индексы в проде реально полезно, но только через контролируемый и хорошо проверенный процесс.

2. Как безопасно удалить неиспользуемые индексы в PostgreSQL

Ниже чеклист в стиле “можно в прод”, который стоит пройти перед удалением любого индекса.

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

Если статистику недавно reset’нули, индекс может выглядеть “неиспользуемым”, хотя он нужен под нагрузкой.

SELECT
datname,
stats_reset
FROM pg_stat_database
WHERE datname = current_database();


Старый stats_reset (или NULL, то есть статистику никогда не сбрасывали) дает больше доверия метрикам использования индексов.

2.2. Проверь, не обслуживает ли индекс constraint

Большой индекс может быть “нулевым” по статистике, но удалять его нельзя, если он обеспечивает PRIMARY KEY, UNIQUE или FOREIGN KEY constraint.

PostgreSQL использует такие индексы для гарантий целостности и не даст их удалить, пока не удалишь сам constraint.

SELECT
i.relname AS index_name,
c.conname AS constraint_name,
c.contype AS constraint_type,
c.conrelid::regclass AS table_name
FROM pg_constraint c
JOIN pg_class i ON i.oid = c.conindid
WHERE i.relname = '<IDX_NAME>';


Если запрос вернул строки, этот индекс удалять нельзя.

2.3. Проверь статистику использования индекса

Так ты подтверждаешь, что планировщик реально не использовал индекс при выполнении запросов.

SELECT
s.indexrelname AS index_name,
s.relname AS table_name,
s.idx_scan,
s.idx_tup_read,
s.idx_tup_fetch
FROM pg_stat_user_indexes s
WHERE s.indexrelname = '<IDX_NAME>';


Все счетчики должны быть 0.

3. Подготовь откат

Перед удалением всегда сохрани DDL индекса, чтобы быстро пересоздать при необходимости.

SELECT pg_get_indexdef('<IDX_NAME>'::regclass) AS create_index_sql;


Сохрани результат как часть rollback-плана.

4. Удаляй безопасно

DROP INDEX CONCURRENTLY не блокирует чтение и запись по таблице, поэтому подходит для прода.

DROP INDEX CONCURRENTLY <IDX_NAME>;


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

5. Итог

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

Не полагайся на статистику в одиночку: проверяй constraints, понимай паттерны нагрузки и всегда готовь rollback.

В проде корректность и стабильность важнее скорости “уборки”.

👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥63👍3