Базы данных (Data Base)
8.05K subscribers
669 photos
479 videos
19 files
688 links
Базы данных (Data Base). По всем вопросам @evgenycarter
Download Telegram
Мини-гайд по трём ключевым сущностям PostgreSQL: соединения, буфер и WAL

1. Соединения (Connections)
PostgreSQL по умолчанию позволяет одновременно до 100 соединений (max_connections).

🔹 Проблема: слишком много прямых соединений создают нагрузку на память и CPU.
🔹 Решение: используйте пуллинг через PgBouncer или Pgpool-II.


[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
pool_mode = transaction
max_client_conn = 500
default_pool_size = 20

🔹 Совет: на проде стремитесь держать max_connections < 200 и масштабируйте через пуллер.


2. Буфер (Shared Buffers & Work Mem)
PostgreSQL активно использует память для кэширования страниц и сортировок.

🔹 shared_buffers – основной буфер кэша:


shared_buffers = 4GB # ≈25% от RAM на выделенном сервере

🔹 work_mem – память на сортировку/слияние одного потока:


work_mem = 64MB # для сложных запросов с сортировками и хэш-джоинами
maintenance_work_mem = 512MB # для VACUUM/CREATE INDEX

🔹 Best practice:

🔹 Установите shared_buffers ≈ 25% RAM.
🔹 Настройте work_mem исходя из числа параллельных операций, не превышайте общий объём памяти.



3. WAL (Write-Ahead Log)
WAL обеспечивает надёжность и репликацию.

🔹 wal_level – детальность логирования:


wal_level = replica # для потоковой репликации

🔹 checkpoint_timeout и max_wal_size:


checkpoint_timeout = 10min
max_wal_size = 1GB

🔹 Архивация WAL для резервных копий:


archive_mode = on
archive_command = 'cp %p /mnt/backup/wal/%f'

🔹 Рекомендации:

🔹 Увеличьте max_wal_size, если у вас большие всплески нагрузки.
🔹 Настройте сжатие WAL (pg_wal) для экономии места.


💡 Сохрани, чтобы не забыть!
А как вы оптимизируете соединения, буфер и WAL в своих проектах?

📲 Мы в MAX

#db

👉 @database_info
👍3🔥2
🎯 Типы баз данных - кратко и по делу

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

🔷 Реляционные (Relational)
Классика: таблицы со строгими схемами и связями.
📌 ACID, SQL, целостность данных
📌 Идеальны для: финансов, e-commerce, CRM, ERP, банков и инвентаризации

🔷 Документные (Document)
Гибкие NoSQL-базы на основе JSON-документов
📌 Горизонтальное масштабирование, вложенные структуры
📌 Подходят для: CMS, каталогов, мобильных и веб-приложений

🔷 In-Memory
Хранят данные в оперативной памяти — максимум скорости
📌 Используются как кэш, для сессий, real-time аналитики
📌 Примеры: Redis, Memcached

🔷 Графовые (Graph)
Работают с узлами и связями - мощные запросы по связности
📌 Идеальны для соцсетей, рекомендаций, мошеннических схем
📌 Пример: Neo4j

🔷 Временные (Time-Series)
Оптимизированы под работу с временными метками
📌 Подходят для метрик, IoT, логов, финансовых данных
📌 Примеры: InfluxDB, TimescaleDB

🔷 Пространственные (Spatial)
Работают с геоданными и координатами
📌 Используются в GIS, логистике, экологии, городском планировании

🔷 Колончатые (Columnar)
Хранят данные по колонкам - супер для аналитики
📌 Быстрые агрегации, параллельная обработка
📌 Используются в BI, отчетах, хранилищах данных
📌 Пример: ClickHouse

🔷 Ключ-Значение (Key-Value)
Простые NoSQL-базы - пара ключ-значение
📌 Идеальны для кэшей, предпочтений, сессий
📌 Примеры: Redis, DynamoDB

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

📲 Мы в MAX

#db

👉 @database_info
👍3🔥1
Мини-гайд: VACUUM в PostgreSQL — когда, зачем и как?

PostgreSQL не удаляет строки сразу при DELETE или UPDATE. Вместо этого они помечаются как "мертвые", а данные продолжают занимать место. Со временем таблицы раздуваются, индексы тормозят, запросы тянут ресурсы.
⠀
💡 VACUUM - инструмент для уборки "мусора" и поддержания БД в форме.

Варианты:

VACUUM — убирает мусор, но не возвращает место ОС.
VACUUM FULL — перезаписывает таблицу и реально освобождает диск (но блокирует таблицу!).
ANALYZE — обновляет статистику планировщика запросов.
VACUUM ANALYZE — два в одном: чистка + статистика.

Когда запускать вручную?
– Если autovacuum не справляется (часто видно по pg_stat_user_tables).
– После больших батчевых удалений/обновлений.
– Перед бэкапом (особенно VACUUM FULL для экономии места).
⠀
Пример:


VACUUM VERBOSE my_table;
VACUUM FULL my_table;


Лайфхаки:

Не злоупотребляй FULL — он тяжёлый.
Настрой autovacuum под нагрузки: autovacuum_vacuum_threshold, autovacuum_vacuum_scale_factor и т.д.
Следи за bloating: pgstattuple и pg_bloat_check.

👉 VACUUM — не уборка по графику, а гигиена твоей БД. Запустишь вовремя - не будет проблем с производительностью.

Сохрани, чтобы не забыть 💾

📲 Мы в MAX

#db

👉 @database_info
🔥5
Антипаттерн: значения по умолчанию NULL везде, где можно

Кажется безобидным: "Ну не знаю я сейчас значение — пусть будет NULL". Но потом:

– Джоины начинают возвращать меньше строк, чем ты ожидал.
– WHERE column = 'X' не находит ничего, потому что там NULL.
– COUNT(column) искажает статистику.
– IS NULL и COALESCE() плодятся по всему коду.

🧱 В чем корень проблемы?
По умолчанию большинство СУБД позволяют NULL, если явно не указано NOT NULL. Это приводит к схеме, где половина полей может быть «ничем», хотя такого смысла в данных нет.

📌 Как избежать?

1. Всегда указывай NOT NULL, если поле обязательно.
2. Думай, нужен ли NULL вообще. Иногда лучше завести отдельный флаг или значение по умолчанию (например, '' или 0).
3. Добавляй ограничения (CHECK), если значение должно быть в определённом диапазоне.
4. Следи за миграциями — новые поля по умолчанию тоже могут быть NULL.

✅ Вывод:
Проектируя схему, подходи к NULL осознанно. Это не просто "ничего" — это потенциальная боль при запросах и анализе.

Сохрани, чтобы не зарываться в NULL -хаос спустя полгода разработки!

📲 Мы в MAX

#db

👉 @database_info
👍2🔥2
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии 📌
https://max.ru/progjob Вакансии в IT

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
👍2
Какой тип индекса выбрать в PostgreSQL?

Индексы — мощный инструмент для ускорения запросов, но не все они одинаково полезны. В PostgreSQL есть несколько типов индексов, и вот как не промахнуться с выбором:


🔹 B-tree (по умолчанию)
📌 Лучший выбор для: =, <, >, BETWEEN, ORDER BY.
✅ Поддерживает сортировку.
💡 Используется в 90% случаев.


CREATE INDEX idx_users_name ON users(name);



🔹 Hash
📌 Только для точного сравнения =.
🚫 Не поддерживает диапазоны, сортировку, LIKE.
⚠️ Редко используется, но может быть быстрее B-tree на =.


CREATE INDEX idx_users_email_hash ON users USING hash(email);



🔹 GIN (Generalized Inverted Index)
📌 Для массивов, jsonb, full-text search.
💡 Отличен при поиске по вложенным структурам или множеству значений.


CREATE INDEX idx_data_tags ON posts USING gin(tags);



🔹 GiST (Generalized Search Tree)
📌 Для геоданных (PostGIS), поиска по диапазонам, tsvector.
💡 Более универсален, но медленнее в некоторых кейсах, чем GIN.


CREATE INDEX idx_events_location ON events USING gist(location);



🔹 BRIN (Block Range Index)
📌 Для огромных таблиц, где данные физически упорядочены.
💡 Занимает очень мало места.
⚠️ Не всегда эффективен — зависит от корреляции данных.


CREATE INDEX idx_logs_timestamp ON logs USING brin(timestamp);



✅ Не кидайтесь ставить индекс "на всякий случай". Подбирай тип под паттерн запроса и тип данных.

📲 Мы в MAX

#db

👉 @database_info
👍4🔥2❤1
SQL vs NoSQL: что выбрать для реального проекта?

Один из самых частых вопросов:
«Нам вообще SQL нужен? Может, сразу MongoDB?»

Разберёмся коротко и по делу 👇


🔷 SQL (PostgreSQL, MySQL, etc.)

Плюсы:
– Строгая схема → меньше ошибок на проде
– Сложные запросы (JOIN, агрегаты) — легко
– ACID-гарантии → важно для денег, заказов, логистики
– Большое комьюнити, mature-тулинги, репликация, индексы

Когда выбирать:
✅ Чёткая структура данных
✅ Много взаимосвязей (нормализация)
✅ Сложные аналитические выборки
✅ Транзакции критичны


🔶 NoSQL (MongoDB, Redis, DynamoDB, etc.)

Плюсы:
– Гибкая схема (можно быстро пихать JSON как есть)
– Горизонтальное масштабирование — встроено
– Подходит для high-load, real-time, event-based систем

Когда выбирать:
✅ Частые изменения структуры данных
✅ Скорость важнее связности
✅ Огромные объёмы с минимальными связями
✅ Event storage, логирование, IoT, временные данные


❗️Частые ошибки:
– "Берём Mongo, потому что модно" — а потом страдаем с джоинами руками
– "Только SQL, потому что так всегда делали" — и не справляемся с масштабом


🔧Часто лучший вариант — гибрид.
Например:
– PostgreSQL → для core бизнес-логики
– Redis → для кеша
– MongoDB → для логов или гибких анкет


Вывод:
Никто не лучше сам по себе. Всё зависит от данных и задач.
А ты чем пользуешься чаще — SQL или NoSQL?

Поделись с командой, если на старте нового проекта 🧠

📲 Мы в MAX

#db

👉 @database_info
👍3
❌ Антипаттерн: UUID как PK без учёта последствий

Выглядит красиво: глобально уникальный идентификатор, можно генерировать на клиенте, удобно в распределённых системах. Но...

💣 Проблемы:
– Большой размер (16 байт vs 4 байта у INT)
– Плохая локальность: индекс B-Tree фрагментируется
– Медленнее вставки, особенно при высоких нагрузках
– Нагружает сеть, если часто передаёшь PK

📉 В PostgreSQL это особенно заметно: индекс на UUID-ключе может вести себя гораздо хуже, чем на BIGSERIAL.


✅ Как делать правильно:

1. Если всё в одной БД: используй BIGINT или BIGSERIAL
2. Если нужен UUID:
– генерируй UUID v7 (появился в 2022, содержит компонент времени → лучше упорядочен)
– либо UUID v1 (временной, но с оговорками по безопасности)
– или комбинируй автоинкремент + случайный суффикс
3. Храни UUID как UUID, а не как VARCHAR(36) — это экономит место и CPU


🧠 UUID — мощный инструмент, но не серебряная пуля. Прежде чем делать его PRIMARY KEY, подумай: что ты реально выигрываешь?

Сохрани, чтобы не собирать фрагментированные индексы вручную 😅

📲 Мы в MAX

#db

👉 @database_info
👍3
Почему одна и та же БД летает на staging и тормозит в проде

Знакомо? На staging сервере — отклик 100мс, на проде — секундные таймауты. Хотя база одна и та же, схема такая же. Что не так?

Вот 5 частых причин:


1. Разный объём данных
На staging — 10k строк, на проде — 10 млн. Индексы, которые "и так нормально", внезапно перестают справляться.

2. Отсутствие/различие индексов
DevOps мог не раскатить нужные индексы в прод. Или, наоборот, staging набит экспериментальными индексами.

3. Параметры конфигурации БД
work_mem, shared_buffers, max_connections — часто в staging минимальны, но в проде тоже забывают подкрутить.

4. Статистика устарела
На проде реже делается ANALYZE, планировщик начинает строить неэффективные планы. Итог — ползёт.

5. Разное поведение приложения
Прод нагружается параллельно десятками потоков. Staging — ты и Postman.


🛠 Что делать:
– Сравни настройки сервера (SHOW ALL;)
– Проверь EXPLAIN ANALYZE
– Не доверяй staging — тестируй на продоподобных данных

📲 Мы в MAX

#db

👉 @database_info
👍3
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии 📌
https://max.ru/progjob Вакансии в IT

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Бонус 📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
Антипаттерн: использование SELECT * в продакшене

Кажется безобидным, правда? Особенно на этапе прототипирования. Но как только ваш запрос с SELECT * уходит в прод, начинаются проблемы:

🔻 Почему это плохо:

– Избыточные данные. Вы тянете всё, включая ненужные поля. Это бьёт по сети, памяти и CPU.
– Ломкость кода. Добавили колонку в таблицу — и, внезапно, старый код падает, потому что ожидал другую структуру.
– Плохая читаемость. Непонятно, какие поля реально нужны. Это мешает отладке и сопровождению.
– Невозможно использовать covering index — индекс по нужным колонкам не спасёт, если вы вытаскиваете всё подряд.

📌 Как правильно:

✅ Явно указывайте нужные поля:


SELECT id, name, created_at FROM users;


✅ Работаете с ORM — настраивайте выборку полей в select() или .only() (в зависимости от фреймворка).

✅ В аналитике? Даже при джойнах и CTE — указывайте, что реально используете.

🧠 Запомни: чем меньше данных ты запрашиваешь — тем быстрее и стабильнее работает твой код.

💬 А ты встречал SELECT * в проде? Или, может, сам когда-то писал так?

📲 Мы в MAX

#db

👉 @database_info
👍4👎1
🔴 Антипаттерн: игнорирование поведения NULL в SQL

Когда ты пишешь WHERE column != 'value', ты можешь думать, что фильтруешь всё, что не равно 'value'. Но если в колонке есть NULL, такие строки выпадут из выборки. Почему? Потому что NULL != 'value' даёт… UNKNOWN, а не TRUE.

❌ Пример проблемы:


SELECT * FROM users
WHERE status != 'active';


Если status у кого-то NULL — он не попадёт в результат. Неочевидно, но критично.

✔️ Как избежать:

1. Явно учитывай NULL'ы:


SELECT * FROM users
WHERE status != 'active' OR status IS NULL;


2. Работай с COALESCE, если допустимо:


SELECT * FROM users
WHERE COALESCE(status, '') != 'active';


📌 То же касается и =: NULL = 'value' → UNKNOWN
📌 Агрегации (COUNT, AVG`) тоже игнорируют `NULL — помни об этом при аналитике

Вывод:
NULL — не "ничего", а "неизвестно", и SQL строго это уважает. Не учитывая это, легко получить баг, который даже не заметишь сразу.

💡 Всегда проверяй поведение WHERE, JOIN и агрегатов с NULL. Пиши явный код, особенно в проде.

Сохрани, чтобы не ловить баги на ровном месте.

📲 Мы в MAX

#db

👉 @database_info
👍3🔥1
3 способа «убить» индекс в SQL

Запрос тормозит. Индекс есть. Что пошло не так?

Вот 3 способа, которыми ты уже мог его сломать:

▪︎ обернул колонку в функцию
▪︎ поставил wildcard % в начале LIKE
▪︎ допустил неявное преобразование типов

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

Главное правило: оставляй колонку “голой” в WHERE.

📲 Мы в MAX

#db

👉 @database_info
👍3🔥2
Что мощнее — S3 или локальные диски?
Разбираем сценарии использования S3-хранилища в связке с Postgres Pro

На вебинаре узнаете о лучших практиках эксплуатации в продакшн-средах. Эксперты Selectel и Postgres Pro разберут все: от резервного копирования через pg_probackup и S3 Selectel до хранения паркетных данных с Postgres Pro AXE и результатов TPC-тестов. Особенно интересно будет архитекторам, техлидам и всем, кто отвечает за надежность и экономику хранения данных.

📍 Онлайн
⏰ 14 июля в 12:00


Регистрируйтесь ➡️ https://slc.tl/hh3pe

Больше мероприятий для ИТ-специалистов в канале @selectel_events. Подписывайтесь!

Реклама. АО "Селектел". erid:2W5zFJxhbub
❤2
🧱 Антипаттерн: использование UUID как Primary Key без оглядки

На первый взгляд, UUID — классный способ генерировать уникальные идентификаторы:
– не зависят от последовательности
– удобны для распределённых систем
– безопасны для внешнего экспонирования

Но если ты просто заменишь SERIAL или BIGINT на UUID в качестве PK — жди сюрпризов:

❌ В чём подвох:
– Производительность INSERT'ов резко падает: UUID случайные → нет locality → индекс (обычно B-Tree) постоянно фрагментируется
– Индексы пухнут: UUID = 16 байт, BIGINT = 8 байт. Разница кажется небольшой, но на больших объёмах — это боль
– Чтение медленнее: за счёт увеличенного размера индексов и меньшего кэш-хита

✅ Как избежать:

1. Если нет жёсткой необходимости в UUID — не используй их как PK
2. Нужен UUID? Сделай его вторичным индексом, а PK оставь автоинкрементным
3. Или хотя бы используй UUID v7 (новый стандарт с time-based префиксом) — он улучшает локальность по сравнению с v4

Пример:


CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
public_id UUID DEFAULT gen_random_uuid() UNIQUE,
name TEXT
);


→ Внутри БД — быстрый BIGINT,
→ Для внешних API — UUID. Удобно и производительно.


📲 Мы в MAX

#db

👉 @database_info
👍5
This media is not supported in your browser
VIEW IN TELEGRAM
Хотите узнать секрет оптимизации SQL-запросов?

Очень важно понимать порядок выполнения.
В SQL-запросе операторы выполняются в следующем порядке:

1. FROM / JOIN
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. DISTINCT
7. ORDER BY
8. LIMIT / OFFSET

📲 Мы в MAX

#db

👉 @database_info
👍2🔥1
Как упростить работу с кластером через веб‑интерфейс OpenSearch Dashboards

Присоединяйтесь к вебинару от Selectel, чтобы разобраться на практике, как развернуть кластер СУБД OpenSearch в облаке за несколько минут и управлять им с помощью веб-интерфейса OpenSearch Dashboards. Узнаете, как легко настроить мониторинг, визуализировать данные и метрики, работать с бэкапами, управлять пользователями и доступами.

📍 Онлайн
⏰ 16 июля в 15:00
👤 Кому будет полезно: сисадминам, архитекторам, администраторам баз данных, бэкэнд-разработчикам, техлидам


Регистрируйтесь ➡️ https://slc.tl/3po0z

Больше мероприятий для ИТ-специалистов в канале @selectel_events. Подписывайтесь!

Реклама. АО "Селектел". erid:2W5zFK5Svmo
❤1
Индексы в PostgreSQL: Часть 1 — B-Tree

Если ты создавал индекс в PostgreSQL по умолчанию, значит, это B-Tree.
Но как он работает и когда он реально полезен?

Что это такое?

B-Tree индекс — сбалансированное дерево поиска.
PostgreSQL автоматически использует его для:

=\` (равенство)
> < >= <= (сравнения)
BETWEEN
LIKE 'abc%' (только префикс, без %abc%).

Пример:


CREATE INDEX idx_users_email ON users (email);
SELECT * FROM users WHERE email = 'test@example.com';


Запрос не будет сканировать всю таблицу — он сразу пойдёт по дереву.

Подводные камни:

1. Не работает для произвольных LIKE:
LIKE '%abc%' → индекс не поможет.
2. Осторожно с функциями:
WHERE LOWER(email) = 'abc' — индекс не используется. Нужен функциональный индекс:


CREATE INDEX idx_users_email_lower ON users (LOWER(email));

3. Многоколонковые индексы:
Порядок важен. (a, b) используется при фильтре по a или по a AND b, но не только по b.

Когда ставить?

- Уникальные поля (email, username).
- Часто используемые фильтры и JOIN-колонки.
- Сортировки (ORDER BY created_at DESC).

Вывод:
B-Tree — твой “универсальный солдат”. Но не пихай его на всё подряд. Перед добавлением — смотри EXPLAIN (ANALYZE).

Сохрани, чтобы не забыть!

📲 Мы в MAX

#db

👉 @database_info
👍4🔥1
🔒 Почему одна "невинная" транзакция может положить продакшн

Классическая ситуация: разработчик открывает транзакцию, делает выборку, потом какой-то API-запрос наружу (например, к платёжному шлюзу), и только потом коммитит. Транзакция висит открытой 3-5 секунд вместо миллисекунд. Локально всё ок, тесты зелёные. В проде — деградация через пару часов.

Что происходит под капотом в PostgreSQL (MVCC):

1. VACUUM не может убрать мёртвые строки. Пока жива хоть одна старая транзакция, движок обязан хранить все версии строк, которые теоретически могут быть видны в её snapshot. UPDATE/DELETE копится в виде dead tuples, автовакуум работает, но эффективность падает.

2. Table bloat. Таблица физически растёт, индексы разбухают, страницы всё реже помещаются в shared_buffers — растёт I/O, падает cache hit ratio.

3. xmin horizon не двигается. Это глобальная граница, до которой можно чистить старые версии. Одна зависшая транзакция держит её на месте для ВСЕЙ базы, а не только для своей таблицы.

4. Реплики страдают отдельно. На hot standby с hot_standby_feedback = on долгая транзакция на реплике заставляет primary тоже не вакуумить нужные строки — эффект расползается по кластеру.

Как ловить:


SELECT pid, now() - xact_start AS duration, query
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC
LIMIT 10;


Плюс idle in transaction — отдельная категория боли: транзакция открыта, а коннекшен вообще ничего не делает (забыли закоммитить/роллбэкнуть). Лечится через idle_in_transaction_session_timeout.

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

#postgresql #databases #mvcc

📲 Мы в MAX

#db

👉 @database_info
👍5🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Чем отличаются друг от друга блокировки баз данных?

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

Основные типы блокировок:

🔴Shared Lock: позволяет нескольким транзакциям одновременно читать ресурс, но не модифицировать его
🔴Exclusive Lock: позволяет транзакции как читать, так и модифицировать ресурс
🔴 Update Lock: используется для предотвращения взаимоблокировки, когда транзакция намеревается обновить ресурс
🔴 Schema Lock: используется для защиты структуры объектов базы данных
🔴 Bulk Update Lock: используется во время массовых вставок
🔴 Key-Range Lock: используется в индексированных данных для предотвращения фантомных чтений
🔴 Row-Level Lock: блокирует конкретную строку в таблице
🔴 Page-Level Lock: блокирует конкретную страницу (фиксированный блок данных) в базе данных
🔴 Table-Level Lock: блокирует всю таблицу

📲 Мы в MAX

#db

👉 @database_info
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍3
Почему Redis такой быстрый (несмотря на однопоточность)?

🔹 Хранение в памяти
Redis хранит все данные в оперативной памяти, где время доступа измеряется наносекундами, а не миллисекундами.

🔹 Однопоточный цикл событий
Redis обрабатывает команды в одном потоке, избегая блокировок, гонок и переключений контекста. Благодаря мультиплексированию ввода-вывода он эффективно обслуживает тысячи одновременных подключений через цикл событий.

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

🔹 Эффективность ввода-вывода
Redis использует лёгкий текстовый протокол RESP для обработки сетевого I/O и поддерживает конвейеризацию, позволяя клиентам отправлять несколько команд в одном запросе.

🔹 Скрипты на стороне сервера
Встроенный движок Lua даёт возможность выполнять сложные многошаговые операции атомарно на сервере, убирая необходимость лишних сетевых запросов.

♻️ Сделай репост, чтобы помочь другим.

📲 Мы в MAX

#db

👉 @database_info
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1🔥1