fa
Feedback
Базы данных (Data Base)

Базы данных (Data Base)

رفتن به کانال در Telegram

Базы данных (Data Base). По всем вопросам @evgenycarter

نمایش بیشتر
8 108
مشترکین
+224 ساعت
-47 روز
-3130 روز
جذب مشترکین
ژوئن '26
ژوئن '26
+42
در 0 کانال‌ها
مه '26
+81
در 0 کانال‌ها
Get PRO
آوریل '26
+56
در 0 کانال‌ها
Get PRO
مارس '26
+85
در 0 کانال‌ها
Get PRO
فوریه '26
+92
در 0 کانال‌ها
Get PRO
ژانویه '26
+82
در 0 کانال‌ها
Get PRO
دسامبر '25
+87
در 0 کانال‌ها
Get PRO
نوامبر '25
+137
در 31 کانال‌ها
Get PRO
اکتبر '25
+101
در 1 کانال‌ها
Get PRO
سپتامبر '25
+178
در 36 کانال‌ها
Get PRO
اوت '25
+159
در 1 کانال‌ها
Get PRO
ژوئیه '25
+197
در 27 کانال‌ها
Get PRO
ژوئن '25
+215
در 19 کانال‌ها
Get PRO
مه '25
+201
در 44 کانال‌ها
Get PRO
آوریل '25
+227
در 40 کانال‌ها
Get PRO
مارس '25
+202
در 38 کانال‌ها
Get PRO
فوریه '25
+176
در 31 کانال‌ها
Get PRO
ژانویه '25
+230
در 33 کانال‌ها
Get PRO
دسامبر '24
+183
در 34 کانال‌ها
Get PRO
نوامبر '24
+188
در 32 کانال‌ها
Get PRO
اکتبر '24
+192
در 29 کانال‌ها
Get PRO
سپتامبر '24
+250
در 28 کانال‌ها
Get PRO
اوت '24
+137
در 17 کانال‌ها
Get PRO
ژوئیه '24
+139
در 0 کانال‌ها
Get PRO
ژوئن '24
+176
در 23 کانال‌ها
Get PRO
مه '24
+169
در 19 کانال‌ها
Get PRO
آوریل '24
+161
در 0 کانال‌ها
Get PRO
مارس '24
+202
در 20 کانال‌ها
Get PRO
فوریه '24
+178
در 18 کانال‌ها
Get PRO
ژانویه '24
+289
در 23 کانال‌ها
Get PRO
دسامبر '23
+246
در 25 کانال‌ها
Get PRO
نوامبر '23
+246
در 17 کانال‌ها
Get PRO
اکتبر '23
+266
در 18 کانال‌ها
Get PRO
سپتامبر '23
+247
در 0 کانال‌ها
Get PRO
اوت '23
+192
در 0 کانال‌ها
Get PRO
ژوئیه '23
+185
در 0 کانال‌ها
Get PRO
ژوئن '23
+223
در 0 کانال‌ها
Get PRO
مه '23
+217
در 0 کانال‌ها
Get PRO
آوریل '23
+309
در 0 کانال‌ها
Get PRO
مارس '23
+282
در 0 کانال‌ها
Get PRO
فوریه '23
+168
در 0 کانال‌ها
Get PRO
ژانویه '23
+175
در 0 کانال‌ها
Get PRO
دسامبر '22
+224
در 0 کانال‌ها
Get PRO
نوامبر '22
+174
در 0 کانال‌ها
Get PRO
اکتبر '22
+321
در 0 کانال‌ها
Get PRO
سپتامبر '22
+380
در 0 کانال‌ها
Get PRO
اوت '22
+295
در 0 کانال‌ها
Get PRO
ژوئیه '22
+538
در 0 کانال‌ها
Get PRO
ژوئن '22
+569
در 0 کانال‌ها
Get PRO
مه '22
+891
در 0 کانال‌ها
Get PRO
آوریل '22
+3 160
در 0 کانال‌ها
تاریخ
رشد مشترکین
اشارات
کانال‌ها
25 ژوئن+1
24 ژوئن+3
23 ژوئن+1
22 ژوئن+2
21 ژوئن+1
20 ژوئن+2
19 ژوئن+2
18 ژوئن+1
17 ژوئن+2
16 ژوئن+1
15 ژوئن+1
14 ژوئن+3
13 ژوئن+2
12 ژوئن+3
11 ژوئن+3
10 ژوئن+1
09 ژوئن+3
08 ژوئن+2
07 ژوئن0
06 ژوئن+1
05 ژوئن+1
04 ژوئن+1
03 ژوئن+2
02 ژوئن+3
01 ژوئن0
پست‌های کانال
Почему одна и та же БД летает на staging и тормозит в проде Знакомо? На staging сервере — отклик 100мс, на проде — секундные
Почему одна и та же БД летает на 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

2
❌ Антипаттерн: UUID как PK без учёта последствий Выглядит красиво: глобально уникальный идентификатор, можно генерировать на
❌ Антипаттерн: 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
424
3
SQL vs NoSQL: что выбрать для реального проекта? Один из самых частых вопросов: «Нам вообще SQL нужен? Может, сразу MongoDB?»
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
415
4
Какой тип индекса выбрать в 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
553
5
🚀 Подборка полезных 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 Питер Новости: Санкт-Петербург / СПБ / ДТП
436
6
Антипаттерн: значения по умолчанию NULL везде, где можно Кажется безобидным: "Ну не знаю я сейчас значение — пусть будет NULL
Антипаттерн: значения по умолчанию 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
463
7
Мини-гайд: VACUUM в PostgreSQL — когда, зачем и как? PostgreSQL не удаляет строки сразу при DELETE или UPDATE. Вместо этого о
Мини-гайд: 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
594
8
🎯 Типы баз данных - кратко и по делу Выбирая базу данных для проекта, важно понимать их ключевые особенности. Ниже - наглядн
🎯 Типы баз данных - кратко и по делу Выбирая базу данных для проекта, важно понимать их ключевые особенности. Ниже - наглядная классификация: 🔷 Реляционные (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
509
9
Мини-гайд по трём ключевым сущностям PostgreSQL: соединения, буфер и WAL 1. Соединения (Connections) PostgreSQL по умолчанию
Мини-гайд по трём ключевым сущностям 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
565
10
Антипаттерн: N+1 запросов и как его избежать Что такое N+1? При выборке связанных данных ORM (или вручную) сначала делается 1
Антипаттерн: N+1 запросов и как его избежать Что такое N+1? При выборке связанных данных ORM (или вручную) сначала делается 1 запрос за основными записями, а потом N дополнительных - по одной для каждой записи, чтобы получить связанные объекты. Например, получить 10 пользователей и для каждого — список их заказов ⇒ 1 запрос к users + 10 запросов к orders. 🚩 # SQLAlchemy-пример “N+1”: users = session.query(User).all() # 1 запрос for u in users: print(u.orders) # для каждого пользователя — отдельный запрос Почему плохо? 🔹 Высокая нагрузка на базу: запросы “в тоненькую” вместо одного “тяжелого”. 🔹 Задержки сети: множество раунд-трипов увеличивает время ответа. 🔹 Масштабируемость страдает: при росте N время растёт линейно. Как победить N+1 1. Eager loading (предварительная загрузка) Загрузка связей сразу вместе с основными объектами. # SQLAlchemy, joinedload - делает JOIN и подтягивает данные сразу from sqlalchemy.orm import joinedload users = session.query(User).options(joinedload(User.orders)).all() for u in users: print(u.orders) # не генерирует дополнительных запросов ✅ Сокращает число запросов до 1. 2. Batch loading (групповые запросы) Если JOIN приводит к дублированию полей, можно сделать два запроса: -- 1: получить user_id SELECT id FROM users WHERE active = true; -- 2: получить все заказы для этих пользователей SELECT * FROM orders WHERE user_id IN (...список id...); ✅ Баланс между сложностью и производительностью. 3. DataLoader / кеширование В GraphQL и приложениях на Node.js часто используют DataLoader: 🔹 Собирает все ключи за тиковый цикл 🔹 Делает один общий запрос 🔹 Раздаёт результаты обратно 4. Правильное проектирование API • Предусматривайте, какие связи нужны на фронтенде, и загружайте их сразу. • Разделяйте endpoints: если нужны только пользователи без заказов - делайте лёгкий запрос. Best practices & подводные камни 🔹 EXPLAIN ANALYZE для проверки плана: убедитесь, что JOIN-ы и IN (…) не приводят к полному сканированию таблиц. 🔹 Пагинация: всегда ограничивайте выборку через LIMIT/OFFSET или курсоры. 🔹 Будьте осторожны с joinedload на “много ко многим” - может раздувать размер результата. Сохрани этот пост, чтобы не забыть, и поделись с коллегами! А у тебя были случаи, когда N+1 съедал всю производительность? Как борешься? 📲 Мы в MAX #db 👉 @database_info
544
11
Мини-гайд: Как не превратить индексы в PostgreSQL в ловушку для производительности Добавил пару-тройку индексов — стало быстр
Мини-гайд: Как не превратить индексы в PostgreSQL в ловушку для производительности Добавил пару-тройку индексов — стало быстрее? Отлично! Но помни: индексы — это не бесплатная магия. Вот что важно учитывать: 1. Индексы ускоряют SELECT, но тормозят INSERT/UPDATE/DELETE. Каждая модификация данных требует обновления всех связанных индексов. Чем их больше — тем медленнее запись. 2. Следи за “мертвыми” индексами. Иногда индексы создают “на всякий случай”, а потом не используют. PostgreSQL сам не удаляет неиспользуемые индексы. Проверь через SELECT * FROM pg_stat_user_indexes WHERE idx_scan = 0; — если idx_scan ноль, пора чистить! 3. Избегай дублирующих индексов. Одинаковые или почти одинаковые индексы — трата ресурсов. Держи только то, что реально нужно для твоих запросов. 4. Регулярно делай REINDEX и VACUUM. Индексы могут фрагментироваться и “раздуваться” из-за удалённых данных. Периодическая чистка — залог стабильной производительности. Вывод: Индексы — мощный инструмент, но требующий внимания. Не ленись мониторить их эффективность, иначе можно только навредить. Сохрани, чтобы не попасть в индекс-ловушку! 📲 Мы в MAX #db 👉 @database_info
611
12
🔗 Сравнение: Типы JOIN в SQL и когда их применять Зачем понимать JOIN’ы? Правильный выбор типа соединения таблиц позволяет п
🔗 Сравнение: Типы JOIN в SQL и когда их применять Зачем понимать JOIN’ы? Правильный выбор типа соединения таблиц позволяет получать необходимые данные эффективно и избегать неожиданных «пустых» или дублирующихся строк. 1. Основные типы JOIN и их поведение INNER JOIN Возвращает только строки, у которых есть совпадения в обеих таблицах. Когда нужно только пересечение данных. LEFT JOIN Берёт все строки из левой таблицы и совпадающие из правой (NULL, если нет). Когда важно сохранить все данные «слева» даже без пары. RIGHT JOIN Аналог LEFT, но берёт все из правой таблицы. Редко используется, чаще удобнее поменять местами таблицы. FULL JOIN Объединяет LEFT и RIGHT: все строки из обеих таблиц, NULL там, где нет пары. Когда нужны все данные из обеих, и нет явного «лево/право». CROSS JOIN Декартово произведение: каждая строка левой с каждой строкой правой. При генерации матриц или тестовых наборов. 2. Примеры синтаксиса -- INNER: только общие заказы и клиенты SELECT o.id, c.name FROM orders o INNER JOIN customers c ON o.customer_id = c.id; -- LEFT: все заказы, даже если клиента нет (NULL) SELECT o.id, c.name FROM orders o LEFT JOIN customers c ON o.customer_id = c.id; -- FULL: все заказы и все клиенты SELECT o.id AS order_id, c.id AS customer_id FROM orders o FULL JOIN customers c ON o.customer_id = c.id; 3. Лучшие практики и советы 1. Всегда уточняйте направление соединения Понимайте, какая таблица «левее»: от этого зависит полнота результатов. 2. Используйте явный JOIN вместо «старого» синтаксиса через WHERE Повышает читабельность и уменьшает риск ошибок. 3. Ограничивайте выборку Добавляйте фильтры (WHERE, ON) до JOIN, чтобы не нагружать соединение лишними данными. 4. Проверяйте результаты на NULL При LEFT/FULL JOIN обрабатывайте NULL через COALESCE или дополнительные условия. 4. Подводные камни 🔹Нежелательный CROSS JOIN Пропущенный условный оператор соединения приведёт к взрывному росту строк. 🔹Производительность JOIN’ы на больших таблицах без индексов по ключам могут быть медленными. 🔹Дублирование Многократное соединение одной таблицы без корректных условий - источник «дублей». Вывод: понимание семантики JOIN’ов - ключ к точной и быстрой выборке данных. Сохрани себе, поделись с коллегами и напиши в комментариях: с каким типом JOIN у тебя чаще всего возникают вопросы? 📲 Мы в MAX #db 👉 @database_info
579
13
Индексы в PostgreSQL: когда и как ставить, чтобы ускорить запросы 🔍 Что такое индекс? Индекс в PostgreSQL - это структура да
Индексы в PostgreSQL: когда и как ставить, чтобы ускорить запросы 🔍 Что такое индекс? Индекс в PostgreSQL - это структура данных (обычно B-tree), позволяющая быстро находить строки по значению столбца, не сканируя всю таблицу. ⚙️ Пример создания простого B-tree-индекса -- Ускоряем поиск по полю email CREATE INDEX idx_users_email ON users (email); ✅ Best Practices 1. Выбирай правильный тип 🔹 BTREE - по умолчанию, для большинства операций сравнения (=, <, >, BETWEEN). 🔹GIN/GiST - для полнотекстового поиска (tsvector), работы с массивами и геоданных. 🔹HASH - для строго равенств (=), но редко нужен. 2. Индексируй часто фильтруемые и сортируемые поля 🔹WHERE, JOIN, ORDER BY. 🔹Например, для запросов типа SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC; создаём составной индекс: CREATE INDEX idx_orders_user_created ON orders (user_id, created_at DESC); 3. Не злоупотребляй 🔹Каждый индекс занимает место и замедляет INSERT/UPDATE/DELETE. 🔹Проанализируй pg_stat_user_indexes и pg_stat_user_tables через pg_stat_statements перед добавлением. 4. Используй частичные индексы Если условие фильтрации редко меняется, можно сузить индекс: CREATE INDEX idx_active_users_email ON users (email) WHERE active = true; 5. Поддерживай актуальность Периодически делай REINDEX или VACUUM ANALYZE для больших таблиц, чтобы индекс не фрагментировался. ❌ Антипаттерн: “Индекс на всё” Создание индекса на каждый столбец: -- Плохо: много маленьких индексов, мало пользы, много затрат CREATE INDEX idx1 ON table(a); CREATE INDEX idx2 ON table(b); CREATE INDEX idx3 ON table(c); ... Проблемы: 🔹Большой объём хранилища. 🔹Замедление DML-операций. 🔹Планы запросов могут пропускать некоторые индексы. 💡 Вывод Правильно подобранные и настроенные индексы - ключ к быстрой работе базы. Сосредоточься на реально востребованных столбцах, комбинируй, не забывай про обслуживание. Сохрани этот мини-гайд, чтобы не забыть, и поделись с коллегами: какие индексы стали для тебя открытием? 📲 Мы в MAX #db 👉 @database_info
822
14
❌ Антипаттерн: булевы значения как строки В таблице users встречал такое: is_active VARCHAR(5) -- значения 'true' или 'false'
❌ Антипаттерн: булевы значения как строки В таблице users встречал такое: is_active VARCHAR(5) -- значения 'true' или 'false' На первый взгляд — ерунда. На практике: – нет валидации: можно вставить 'tru', 'yes', '0', – медленнее сравнение, чем у BOOLEAN, – больше места в хранилище, – сложно агрегировать и строить аналитику. 🔧 Как надо: is_active BOOLEAN DEFAULT true – Экономия места (1 байт против 5 и больше) – Проверка через WHERE is_active – Простой COUNT(*) FILTER (WHERE is_active) для отчётов – Автоматическая поддержка в ORM и UI-форматах 📌 Даже если тебе нужно больше состояний - используй ENUM, а не строку. 💡Чем проще тип, тем меньше шансов на баг. Сохрани, если в коде встречал такое - и переделай с чистой совестью. 📲 Мы в MAX #db 👉 @database_info
807
15
🔧 Mini-гайд: ускоряем JOIN-ы в больших таблицах JOIN-ы - мощный инструмент SQL, но на больших объёмах данных могут стать узк
🔧 Mini-гайд: ускоряем JOIN-ы в больших таблицах JOIN-ы - мощный инструмент SQL, но на больших объёмах данных могут стать узким горлышком. Вот 5 проверенных способов ускорить их: 1. Индексы по ключам соединения Без индекса - каждый JOIN превращается в полный перебор. ➤ Пример: CREATE INDEX idx_user_id ON orders(user_id); 2. Ограничь объём данных до JOIN-а Фильтруй и агрегируй данные до объединения. ➤ Вместо: SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE u.country = 'DE'; ➤ Лучше: WITH german_users AS ( SELECT id FROM users WHERE country = 'DE' ) SELECT * FROM orders o JOIN german_users g ON o.user_id = g.id; 3. Учитывай тип JOIN-а INNER JOIN обычно быстрее OUTER JOIN, особенно при наличии NOT NULL. Иногда EXISTS работает быстрее, чем LEFT JOIN. 4. Следи за типами данных JOIN по полям с разными типами (например, int и varchar) = неэффективный cast + тормоза. 5. Проверь планы выполнения (EXPLAIN) Не гадай, а смотри, что реально происходит. EXPLAIN ANALYZE - твой друг. 📌 Даже один лишний JOIN может уронить производительность. Внимательность + EXPLAIN = уверенность. Поделись с коллегами - спасёшь чей-то прод. 📲 Мы в MAX #db 👉 @database_info
808
16
Антипаттерн: SELECT * - удобно, но опасно Использовать SELECT * - значит звать всех на вечеринку, даже если звал только двоих
Антипаттерн: SELECT * - удобно, но опасно Использовать SELECT * - значит звать всех на вечеринку, даже если звал только двоих. Почему это плохо: 🔹 Излишняя нагрузка на сеть и СУБД - выбираются все столбцы, включая ненужные. 🔹 Проблемы с индексами - СУБД может не использовать покрывающий индекс. 🔹 Ломается при изменении схемы - добавил столбец → внезапно изменилось поведение приложения. 🔹 Сложнее читать и поддерживать - особенно в JOIN’ах. ✅ Как правильно: Запрашивай только нужные поля: SELECT id, name, created_at FROM users; 📌 И даже в админках/аналитике лучше явно указывать поля - это дисциплинирует. Хочешь писать код, который легко масштабировать и отлаживать - забудь про SELECT *. Сохрани, чтобы не забыть 💾 Поделись с коллегами, которые всё ещё "звёздят" в SQL ✨ 📲 Мы в MAX #db 👉 @database_info
874
17
🚀 Подборка полезных 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 лайфхак 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 Питер Новости: Санкт-Петербург / СПБ / ДТП
764
18
🛑 Антипаттерн: "Списки через запятую" в базе данных Признайтесь, у каждого был соблазн сделать это. У вас есть сущность (нап
🛑 Антипаттерн: "Списки через запятую" в базе данных Признайтесь, у каждого был соблазн сделать это. У вас есть сущность (например, User), и нужно сохранить список их ролей или IDs купленных товаров. Создавать отдельную таблицу кажется оверхедом, и вы решаете: "А, запишу просто строкой через запятую". В БД это выглядит так: role_ids: "1,4,12" Почему это бомба замедленного действия и как это лечить? Давайте разбираться. Почему это плохо (The Pain): 1. Сложный поиск. Найти всех пользователей с role_id = 1 через LIKE '%1%' - это больно. Вы найдете и 1, и 12, и 100. Придется писать монструозные регулярки. 2. Никаких индексов. База данных не может эффективно индексировать подстроки в таком формате. Full scan обеспечен. 3. Проблемы с JOIN. Вы не сможете сделать нормальный JOIN с таблицей ролей. 4. Целостность данных. Вы не можете повесить Foreign Key. Никто не помешает записать туда "1, 4, apple, NULL". 5. Атомарность обновлений. Удалить роль 4 из строки "1,4,12" - это чтение, парсинг на бекенде и перезапись. Состояние гонки (race condition) гарантировано. Как делать правильно: Вариант 1: Классическая нормализация (Junction Table) Создайте связующую таблицу. Это золотой стандарт для реляционных БД (PostgreSQL, MySQL, Oracle). -- Плохо ❌ CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), role_ids VARCHAR(255) -- "1,2" ); -- Хорошо ✅ CREATE TABLE user_roles ( user_id INT, role_id INT, PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (role_id) REFERENCES roles(id) ); Теперь выборка всех админов - это моментальный запрос с использованием индексов. Вариант 2: Массивы или JSONB (PostgreSQL) Если вы используете PostgreSQL и вам действительно не нужны жесткие FK (Foreign Keys) на каждый элемент, можно использовать нативные типы. -- Допустимо в Postgres ✅ CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT, role_ids INT[] -- массив целых чисел ); -- Поиск (очень быстрый с GIN индексом): SELECT * FROM users WHERE 1 = ANY(role_ids); Никогда не храните списки в VARCHAR, если вам когда-либо придется искать по содержимому этого списка или джойнить его. Экономия 5 минут на старте обернется часами рефакторинга позже. 📲 Мы в MAX #db 👉 @database_info
841
19
PostgreSQL или MySQL? Один из самых частых вопросов от разработчиков и DevOps - “Что лучше: PostgreSQL или MySQL?”. Давай без
PostgreSQL или MySQL? Один из самых частых вопросов от разработчиков и DevOps - “Что лучше: PostgreSQL или MySQL?”. Давай без фанатизма, просто по фактам 👇 🔷 PostgreSQL: 🔵Поддержка JSONB с индексами - почти как NoSQL внутри SQL 🔵CTE, оконные функции, полнотекстовый поиск - топ для аналитики 🔵Расширяемость: можно писать свои типы, функции, операторы 🔵Хорош для сложных запросов, аналитики, геоданных (PostGIS) 🔻 Минусы: – Сложнее в настройке и оптимизации – Меньше хостингов out-of-the-box (но всё быстро меняется) 🔶 MySQL (особенно InnoDB / MariaDB): 🔵Быстрее на простых SELECT/INSERT, если запросы примитивные 🔵Больше ready-to-go хостингов и тулов для web 🔵Низкий порог входа - быстрее поднимается новичками 🔻 Минусы: – Слабее в сложных SQL-конструкциях – Нет нормальной поддержки CTE до недавнего времени – JSON без индексации (в MySQL < 8.0) Вывод: 🧠 Если делаешь CRM, веб-продукт или MVP с простыми запросами, MySQL зайдёт. 📊 Если строишь data-heavy приложения, BI, ETL или гео-системы, PostgreSQL без шансов. 📲 Мы в MAX #db 👉 @database_info
869
20
Разбор кейса. Компания переехала с MongoDB на PostgreSQL - зачем и что пошло не так. Стартап хранил всё в MongoDB — быстро, у
Разбор кейса. Компания переехала с MongoDB на PostgreSQL - зачем и что пошло не так. Стартап хранил всё в MongoDB — быстро, удобно, JSON-документы летят. Но через год — бизнес растёт, появляются проблемы: 🔸 Запросы тормозят. Mongo не любит сложные агрегаты с джойнами по коллекциям. А бизнесу уже нужно: – аналитика по заказам – ретеншн-отчёты – CRM-связи между сущностями 🔸 Дублирование данных. Документы растут, становятся вложенными, обновлять — боль. Классическая проблема: “Обновили e-mail юзера — забыли в двух местах”. 🔸 Сложность поддержки. Без схемы трудно отследить, что где лежит. Новым разработчикам — боль. 🔁 Решение: PostgreSQL – Явная схема → валидируем данные сразу – Поддержка JSONB → можно переехать частями – Сильный SQL → отчёты, джойны, агрегации — на ура – Надёжность и mature-инструменты для миграций, бэкапов, мониторинга ⚠️ Подводные камни: – Миграция данных: пришлось писать парсеры и валидаторы – Пришлось переосмыслить структуру: из “гибкого” хаоса в нормализованную модель – Команда училась писать SQL и настраивать индексы ✅ Зато теперь: – Запросы летят – Данные валидны – Аналитика возможна – Рост — без боли Переход с NoSQL на SQL — это не “откат назад”, это осознанный апгрейд, когда бизнесу нужен контроль, скорость и предсказуемость. 📲 Мы в MAX #db 👉 @database_info
982