Тулза для мажорного апгрейда версии получила несколько приятных новых фич в Postgres 18. Нам особенно нравится, что теперь можно переносить статистику по таблицам, значит, сразу после апгрейда производительность будет нормальной, без долгого разогрева.
👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤3
SCRAM уже давно стал предпочтительным способом хеширования паролей вместо MD5 у большинства. Postgres сейчас постепенно выводит MD5 из употребления: в Postgres 18 уже появляются предупреждения, а в Postgres 19, скорее всего, депрекейтнут еще жестче. Проверьте старые пароли и обновите их как можно скорее 🙏
👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
PostgreSQL делает одну хитрую оптимизацию, из-за которой некоторые сканы становятся index-only и запрос выполняется быстрее. Вот как это работает…
Index-only scan это когда PostgreSQL забирает данные полностью из индекса, не обращаясь к реальным строкам таблицы (heap). Это сильно быстрее, потому что убирается лишний шаг чтения строк с диска.
Чтобы index-only scan реально работал, PostgreSQL должен быть уверен, что данные в индексе актуальны. Из-за реализации MVCC одна и та же строка может существовать в нескольких версиях, которые используются разными активными транзакциями.
В не оптимизированном варианте PostgreSQL пришлось бы читать реальную строку, чтобы проверить ее видимость (visibility) и при необходимости взять последнюю версию. Из-за этого index-only scans могут быть не такими быстрыми, как хотелось бы. Чтобы ускорить это, PostgreSQL использует Visibility Map.
Visibility Map это внутренняя структура данных, которую PostgreSQL ведет, чтобы отслеживать, какие страницы (блоки строк) в таблице содержат только такие tuple (строки), которые видимы всем транзакциям. Если страница помечена в visibility map как
Поэтому во время index-only scan PostgreSQL сначала вычисляет строки, которые должны попасть в результат, а потом смотрит в visibility map, помечена ли соответствующая страница как
В PostgreSQL из-за MVCC операции update и delete приводят к появлению dead tuples, и чтобы их очистить, нужен vacuum. Поэтому в процессе vacuuming:
1. удаляются dead tuples, и
2. обновляется visibility map, чтобы пометить страницы как
Это означает, что каждая строка на этой странице видима всем транзакциям, и теперь можно пропускать heap fetch и выполнять index-only scans быстрее.
👉 @SQLPortal
Index-only scan это когда PostgreSQL забирает данные полностью из индекса, не обращаясь к реальным строкам таблицы (heap). Это сильно быстрее, потому что убирается лишний шаг чтения строк с диска.
Чтобы index-only scan реально работал, PostgreSQL должен быть уверен, что данные в индексе актуальны. Из-за реализации MVCC одна и та же строка может существовать в нескольких версиях, которые используются разными активными транзакциями.
В не оптимизированном варианте PostgreSQL пришлось бы читать реальную строку, чтобы проверить ее видимость (visibility) и при необходимости взять последнюю версию. Из-за этого index-only scans могут быть не такими быстрыми, как хотелось бы. Чтобы ускорить это, PostgreSQL использует Visibility Map.
Visibility Map это внутренняя структура данных, которую PostgreSQL ведет, чтобы отслеживать, какие страницы (блоки строк) в таблице содержат только такие tuple (строки), которые видимы всем транзакциям. Если страница помечена в visibility map как
all-visible, движок понимает, что ему не нужно проверять видимость отдельных строк на этой странице.Поэтому во время index-only scan PostgreSQL сначала вычисляет строки, которые должны попасть в результат, а потом смотрит в visibility map, помечена ли соответствующая страница как
all-visible. Если да, он пропускает чтение этой страницы из heap, и выполнение становится быстрее и эффективнее.В PostgreSQL из-за MVCC операции update и delete приводят к появлению dead tuples, и чтобы их очистить, нужен vacuum. Поэтому в процессе vacuuming:
1. удаляются dead tuples, и
2. обновляется visibility map, чтобы пометить страницы как
all-visible.Это означает, что каждая строка на этой странице видима всем транзакциям, и теперь можно пропускать heap fetch и выполнять index-only scans быстрее.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
Никогда не используй COUNT для проверки существования
Если тебе нужно просто понять, есть ли конкретная запись в данных, не используй
Проблема в том, что
Когда ты пишешь
Вместо
С
👉 @SQLPortal
Если тебе нужно просто понять, есть ли конкретная запись в данных, не используй
COUNT() с фильтром (WHERE).SELECT COUNT(*)
FROM users
WHERE email = 'johnfake@analytica.com';
Проблема в том, что
COUNT(*) отвечает на другой вопрос. Он считает, сколько строк подходит под условие, хотя тебе нужно только понять, существует ли хотя бы одна.Когда ты пишешь
COUNT(*), база может пройтись по всем подходящим строкам, чтобы вычислить итоговое число. Даже если совпадение нашлось сразу, она может продолжить, потому что ты попросил полный подсчет. На больших таблицах это лишняя работа.Вместо
COUNT() используй EXISTS:SELECT EXISTS (
SELECT 1
FROM users
WHERE email = 'johnfake@analytica.com'
);
С
EXISTS база остановится, как только найдет первое совпадение. Никакого подсчета, никакого лишнего сканирования.Please open Telegram to view this post
VIEW IN TELEGRAM
❤17
Если ты читал предыдущий пост про буферы, ты уже знаешь: PostgreSQL вообще не обязан “думать” про твои строки. Ты можешь вставлять профиль пользователя или доставать платежные данные, но для Postgres все это просто блоки данных. Конкретно блоки по 8KB. Хочешь получить одну маленькую строку? PostgreSQL тащит с диска целую страницу на 8 192 байта, чтобы отдать тебе ее. Обновляешь один булевый флаг? Та же история. 8KB-страница это атомарная единица I/O.
Но просто знать, что эти страницы существуют, мало. Чтобы понять, почему база ведет себя так, как ведет, надо понимать, как она устроена. Каждый раз, когда ты выполняешь
Буферный пул кеширует эти страницы, Write-Ahead Log (WAL) защищает их, а
Читать гайд
👉 @SQLPortal
Но просто знать, что эти страницы существуют, мало. Чтобы понять, почему база ведет себя так, как ведет, надо понимать, как она устроена. Каждый раз, когда ты выполняешь
INSERT, PostgreSQL должен решить, как упаковать запись в одну из этих страниц по 8 192 байта.Буферный пул кеширует эти страницы, Write-Ahead Log (WAL) защищает их, а
VACUUM вычищает. Глубокое погружение во внутренности хранения PostgreSQL начинается с понимания того, что вообще происходит внутри этих 8KB-страниц. Страниц, которые PostgreSQL использует, чтобы организовать все данные: таблицы, индексы, последовательности (sequences), TOAST-отношения (relations).Читать гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
boringSQL | Supercharge your SQL & PostgreSQL powers
Introduction to Buffers in PostgreSQL
How PostgreSQL actually manages memory, from shared_buffers and dirty pages to the OS page cache sitting underneath it all.
❤3👍3
Удалять огромную пачку строк (скажем, миллион) одним
Когда ты делаешь большой
На нагруженных системах (много чтений и апдейтов) это разъезжается волной. Чтения начинают копиться, записи блокируются, пул соединений забивается. Такой “клининг” очень легко превращается в продовый инцидент :)
Есть еще WAL (transaction log). Массовый
Фикс простой: удаляй батчами.
Забавный факт: базы не спасут тебя от тебя самого :) Это как раз из тех вещей, которые ты усваиваешь один раз, обычно на факапах. Не спрашивай, откуда знаю :)🎉
👉 @SQLPortal
DELETE кажется эффективным. На деле нет. Так можно легко положить базу.Когда ты делаешь большой
DELETE одним запросом, база держит блокировки на всех затронутых строках до конца операции. Если запрос выполняется 30 секунд, блокировки висят 30 секунд. Любые другие запросы, которым нужны эти строки, встают и ждут.На нагруженных системах (много чтений и апдейтов) это разъезжается волной. Чтения начинают копиться, записи блокируются, пул соединений забивается. Такой “клининг” очень легко превращается в продовый инцидент :)
Есть еще WAL (transaction log). Массовый
DELETE генерит огромный объем логов разом, что может резко поднять disk I/O и замедлить репликацию. Реплики начинают отставать, иногда очень заметно.Фикс простой: удаляй батчами.
DELETE ... WHERE ... LIMIT 1000, потом небольшая пауза, потом повтор. По общему времени это может быть дольше, зато блокировки короткие, записи в WAL размазаны по времени, и база остается отзывчивой.Забавный факт: базы не спасут тебя от тебя самого :) Это как раз из тех вещей, которые ты усваиваешь один раз, обычно на факапах. Не спрашивай, откуда знаю :)
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7❤6
Миф, что реляционные БД не масштабируются!!!
Zerodha, один из крупнейших брокеров Индии, придумал любопытный способ решать проблему с отчетами.
В этом видео CTO Zerodha, Kailash Nadh, рассказывает про софтверный хак под названием Dung Beetle, который помогает вытягивать огромные объемы отчетности по сотням миллиардов финансовых записей.
Система работает как асинхронный middleware: она не дает базе лечь, ставит сложные SQL-запросы в очередь и выполняет их исходя из доступной мощности бэкенда. Вместо классического кэширования результаты каждого отдельного отчета сохраняются в уникальную временную таблицу в выделенном инстансе PostgreSQL.
Из-за такого нестандартного подхода каждый день создается больше семи миллионов независимых таблиц, что показывает, насколько далеко можно выжать масштабируемость и живучесть PostgreSQL.
Вынеся тяжелую отчетность в этот эфемерный слой результатов, компания может отдавать данные мгновенно миллионам пользователей, не трогая производительность основной базы. Вся архитектура сбрасывается каждую ночь просто заменой диска, чтобы система оставалась легкой и эффективной.
👉 @SQLPortal
Zerodha, один из крупнейших брокеров Индии, придумал любопытный способ решать проблему с отчетами.
В этом видео CTO Zerodha, Kailash Nadh, рассказывает про софтверный хак под названием Dung Beetle, который помогает вытягивать огромные объемы отчетности по сотням миллиардов финансовых записей.
Система работает как асинхронный middleware: она не дает базе лечь, ставит сложные SQL-запросы в очередь и выполняет их исходя из доступной мощности бэкенда. Вместо классического кэширования результаты каждого отдельного отчета сохраняются в уникальную временную таблицу в выделенном инстансе PostgreSQL.
Из-за такого нестандартного подхода каждый день создается больше семи миллионов независимых таблиц, что показывает, насколько далеко можно выжать масштабируемость и живучесть PostgreSQL.
Вынеся тяжелую отчетность в этот эфемерный слой результатов, компания может отдавать данные мгновенно миллионам пользователей, не трогая производительность основной базы. Вся архитектура сбрасывается каждую ночь просто заменой диска, чтобы система оставалась легкой и эффективной.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15😁8🔥5
Совет по Postgres: не давай блокировкам висеть бесконечно, задай таймаут на ожидание лока.
👉 @SQLPortal
SET lock_timeout = '10s';
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
Как убрать тормоза ORM на 80% с помощью грамотных индексов в PostgreSQL
Современные приложения часто плотно завязаны на ORM (Object-Relational Mapper) ради быстрой разработки. ORM реально ускоряют разработку, но при этом нередко генерируют запросы, которые не до конца оптимальны с точки зрения производительности базы. В такой ситуации у инженеров по БД мало контроля над тем, как именно выглядят запросы, поэтому индексация и тюнинг базы остаются главными инструментами для ускорения.
В этой статье покажут, как чуваки заметно улучшили производительность PostgreSQL для одного из их enterprise-клиентов, применив стратегическую индексацию и не меняя запросы приложения.
👉 @SQLPortal
Современные приложения часто плотно завязаны на ORM (Object-Relational Mapper) ради быстрой разработки. ORM реально ускоряют разработку, но при этом нередко генерируют запросы, которые не до конца оптимальны с точки зрения производительности базы. В такой ситуации у инженеров по БД мало контроля над тем, как именно выглядят запросы, поэтому индексация и тюнинг базы остаются главными инструментами для ускорения.
В этой статье покажут, как чуваки заметно улучшили производительность PostgreSQL для одного из их enterprise-клиентов, применив стратегическую индексацию и не меняя запросы приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
Stormatics
Fixing ORM Slowness by 80% with Strategic PostgreSQL Indexing | Stormatics
Boost PostgreSQL performance by 80% with strategic indexing, reduce sequential scans and IOPS without changing application code.
👍1
Хватит объяснять SQL JOIN’ы через диаграммы Венна.
Вот 4 картинки, которые показывают это намного логичнее:
👉 @SQLPortal
Вот 4 картинки, которые показывают это намного логичнее:
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14😁1
Один чувак написал подробный разбор того, как базы данных на самом деле выполняют JOIN'ы.
В этом разборе он объясняет, какие алгоритмы работают под капотом, когда мы используем JOIN: nested loop join, hash join, merge join, index join, grace hash join и broadcast join, а также почему query planner выбирает один вариант вместо другого.
Если тебе было интересно, почему в одном случае JOIN срабатывает мгновенно, а в другом ужасно тормозит, или как базы данных эффективно джойнят таблицы с миллиардами строк, этот материал поможет собрать четкую ментальную модель. Почитай.
👉 @SQLPortal
В этом разборе он объясняет, какие алгоритмы работают под капотом, когда мы используем JOIN: nested loop join, hash join, merge join, index join, grace hash join и broadcast join, а также почему query planner выбирает один вариант вместо другого.
Если тебе было интересно, почему в одном случае JOIN срабатывает мгновенно, а в другом ужасно тормозит, или как базы данных эффективно джойнят таблицы с миллиардами строк, этот материал поможет собрать четкую ментальную модель. Почитай.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Нужно быстро поднять PostgreSQL для MVP или pet-проекта?
В MWS Cloud Platform база данных PostgreSQL разворачивается за минуты и сразу готова к работе:
Подходит для любого проекта — от интернет-магазина до высоконагруженного backend-сервиса.
🆓 До 31 марта production-ready PostgreSQL в облаке — бесплатно
🔥 Запустите свой проект, протестируйте под нагрузкой и спокойно оставляйте базу в продакшене.
Попробовать бесплатно*
* Скидка 100% на оплату сервиса Managed PostgreSQL предоставляется в период с 9 февраля по 31 марта 2026 года для участников акции. Подробные условия — по ссылке
В MWS Cloud Platform база данных PostgreSQL разворачивается за минуты и сразу готова к работе:
⏺️ готовые конфигурации CPU и RAM под разные типы нагрузок⏺️ high availability или standalone конфигурации, автоматические бэкапы⏺️ гарантированные мощности CPU, консистентный API и удобный cloud-native IAM⏺️ сетевые или сверхбыстрые NVMe-диски под разные сценарии⏺️ постоянный primary endpoint: адрес не меняется при failover или switchover⏺️ до 3 read-only точек подключения — удобно для подключения аналитики⏺️ поддержка популярных расширений PostgreSQL "из коробки"
Подходит для любого проекта — от интернет-магазина до высоконагруженного backend-сервиса.
Попробовать бесплатно*
* Скидка 100% на оплату сервиса Managed PostgreSQL предоставляется в период с 9 февраля по 31 марта 2026 года для участников акции. Подробные условия — по ссылке
Please open Telegram to view this post
VIEW IN TELEGRAM
В PostgreSQL 19 (dev) прилетели еще 2 полезных изменения:
1. Разрешили
2. Запретили
Небольшие изменения, но оба коммита полезные:
- первый про более гибкую работу с virtual columns
- второй про ужесточение/санитизацию имен и снижение странных кейсов
👉 @SQLPortal
1. Разрешили
ALTER COLUMN SET EXPRESSION для виртуальных столбцов с CHECK-ограничениями 2. Запретили
CR и LF в именах баз данных, ролей и табличных пространств Небольшие изменения, но оба коммита полезные:
- первый про более гибкую работу с virtual columns
- второй про ужесточение/санитизацию имен и снижение странных кейсов
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В Postgres можно делать функциональные индексы для запросов, которые приходят в конкретном формате. Например, для
👉 @SQLPortal
TIMESTAMP, когда в запросе фильтрация идет только по дате:CREATE INDEX idx_orders_dt_only ON orders ((created_at::date));
SELECT count(*) FROM orders WHERE created_at::date = '2024-05-20';
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🤯2❤1
В Postgres 18 появился новый метод клонирования для создания баз данных из шаблонных (template) БД, который работает заметно быстрее, чем другие способы. Это работает на конкретных файловых системах, которые поддерживают copy-on-write / reflink.
👉 @SQLPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Какой SQL-запрос работает быстрее?
vs
👉 @SQLPortal
SELECT * FROM orders
WHERE status = 'NEW'
OR status = 'PENDING'
OR status = 'PROCESSING';
vs
SELECT * FROM orders
WHERE status IN ('NEW', 'PENDING', 'PROCESSING');
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔7❤2
Перестань переписывать JOIN через ON; используй USING
Если ты давно пишешь JOIN’ы в SQL, ты наверняка привык к
Вот почему стоит подумать о переходе.
Намного чище, да?
Перейти на
👉 @SQLPortal
Если ты давно пишешь JOIN’ы в SQL, ты наверняка привык к
ON. Оно работает и делает свою работу. Но когда ты джоинишь две таблицы по колонкам с абсолютно одинаковым именем, есть более чистый и аккуратный вариант: USING.Вот почему стоит подумать о переходе.
SELECT
e.Employee_ID,
e.Employee_Name,
e.Department,
s.Net_Sales
FROM Employees e
JOIN sales s
ON e.Employee_ID = s.Employee_ID;
ON ок, но оно многословное. Приходится повторять и имена таблиц, и имена колонок. Если имя колонки одинаковое в обеих таблицах, ты по сути пишешь одно и то же дважды. Хуже того: когда выбираешь колонки, можешь получить два столбца Employee_ID, если явно не квалифицировать их.USING это сокращение для join’ов по равенству, когда колонки называются одинаково. Та же самая выборка будет такой:SELECT
e.Employee_ID,
e.Employee_Name,
e.Department,
s.Net_Sales
FROM Employees e
JOIN sales s
USING (Employee_ID);
Намного чище, да?
USING автоматически сопоставляет колонки с одинаковым именем и делает inner join (или left/right join, в зависимости от типа join). Ты указываешь имя колонки один раз.Перейти на
USING это маленькое изменение, которое делает SQL короче и более “самодокументируемым”. Меньше шансов ошибиться, и результирующий набор получается аккуратнее. В следующий раз, когда джоинишь по одинаково названным колонкам, выкинь ON и попробуй USING. Только проверь, что твоя СУБД поддерживает USING.Please open Telegram to view this post
VIEW IN TELEGRAM
❤9