uk
Feedback

Не попадись на ботовода! Telemetrio знаходить і позначає такі канали мітками 👉 Хочеш бачити мітку, оформляй підписку

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

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

Відкрити в Telegram

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

Показати більше
8 021
Підписники
+124 години
-47 днів
-2030 днів
Архів дописів
🎯 Типы баз данных - кратко и по делу Выбирая базу данных для проекта, важно понимать их ключевые особенности. Ниже - наглядн
🎯 Типы баз данных - кратко и по делу Выбирая базу данных для проекта, важно понимать их ключевые особенности. Ниже - наглядная классификация: 🔷 Реляционные (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

Антипаттерн: 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

Мини-гайд: Как не превратить индексы в 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

🔗 Сравнение: Типы 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

❌ Антипаттерн: булевы значения как строки В таблице 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

🔧 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

Pghero Панель управления производительностью для Postgres https://github.com/ankane/pghero 📲 Мы в MAX #db 👉 @database_info
Pghero Панель управления производительностью для Postgres https://github.com/ankane/pghero 📲 Мы в MAX #db 👉 @database_info

Антипаттерн: SELECT * - удобно, но опасно Использовать SELECT * - значит звать всех на вечеринку, даже если звал только двоих
Антипаттерн: SELECT * - удобно, но опасно Использовать SELECT * - значит звать всех на вечеринку, даже если звал только двоих. Почему это плохо: 🔹 Излишняя нагрузка на сеть и СУБД - выбираются все столбцы, включая ненужные. 🔹 Проблемы с индексами - СУБД может не использовать покрывающий индекс. 🔹 Ломается при изменении схемы - добавил столбец → внезапно изменилось поведение приложения. 🔹 Сложнее читать и поддерживать - особенно в JOIN’ах. ✅ Как правильно: Запрашивай только нужные поля:

SELECT id, name, created_at FROM users;
📌 И даже в админках/аналитике лучше явно указывать поля - это дисциплинирует. Хочешь писать код, который легко масштабировать и отлаживать - забудь про SELECT *. Сохрани, чтобы не забыть 💾 Поделись с коллегами, которые всё ещё "звёздят" в SQL ✨ 📲 Мы в MAX #db 👉 @database_info

Postgres против MySQL. Postgres спроектирован как единая, целостная система, и этот архитектурный подход определяет принципы работы всех остальных компонентов. Данные хранятся в виде «кучи» (heap), где могут одновременно существовать несколько версий одной и той же строки. При обновлении создаются новые версии, а старые сохраняются до тех пор, пока не будут удалены в процессе очистки (VACUUM). Механизм MVCC (многоверсионное управление параллельным доступом) встроен непосредственно в модель данных, что открывает широкие возможности для индексации и расширения функциональности. В основе MySQL лежит архитектура с подключаемыми модулями хранения (storage engines). Уровень SQL находится «сверху», а за хранение данных отвечает движок InnoDB. Старые версии строк хранятся в журналах отката (undo logs) и восстанавливаются по мере необходимости. Данные организованы в виде кластеризованного индекса, где первичный ключ определяет их физическое расположение. 📲 Мы в MAX #db 👉 @database_info

🛑 Антипаттерн: "Списки через запятую" в базе данных Признайтесь, у каждого был соблазн сделать это. У вас есть сущность (нап
🛑 Антипаттерн: "Списки через запятую" в базе данных Признайтесь, у каждого был соблазн сделать это. У вас есть сущность (например, 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

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

💣 NULL — тихий саботаж в твоей БД На первый взгляд, NULL — просто отсутствие значения. Но на практике это частый источник ба
💣 NULL — тихий саботаж в твоей БД На первый взгляд, NULL — просто отсутствие значения. Но на практике это частый источник багов, неверных аналитик и проблем в бизнес-логике. 📉 Антипаттерн: беспечное обращение с NULL Примеры:

SELECT * FROM users WHERE age > 18;  -- Пользователи с age = NULL не попадут
Ты думаешь, что отбираешь всех взрослых, но age = NULL тут "выпадает", ведь NULL > 18 → UNKNOWN.

WHERE col1 = col2  -- Не сработает, если хотя бы одно значение NULL
🙈 Проблема: NULL не равно даже самому себе (NULL != NULL). 📉 Итоги: ошибки в JOIN'ах, WHERE-фильтрах, расчетах. 🛡 Как защититься: ✅ Явно учитывай NULL:

WHERE age > 18 OR age IS NULL  -- если хочешь включить "неизвестный возраст"
✅ Используй COALESCE:

SELECT COALESCE(discount, 0) FROM orders  -- подставим 0, если скидка не указана
✅ Проверяй NULL через IS NULL / IS NOT NULL ✅ Для агрегаций учитывай поведение NULL:

AVG(column)  -- пропустит NULL'ы, но COUNT(column) тоже не посчитает их!
Вывод: NULL — не "ничего", а "неизвестно". Пиши запросы так, как будто NULL всегда где-то прячется — и он не на твоей стороне. Сохрани, чтобы не ловить грабли 💥 📲 Мы в MAX #db 👉 @database_info

⚡️ Индексы в базах данных: как заставить запросы летать Представь, что тебе нужно найти нужную главу в техническом справочнике на 1000 страниц. Без оглавления придется листать всё подряд (в базах данных это называется Full Table Scan - страшный сон любого админа). Индекс - это и есть то самое оглавление. Как это работает под капотом? Чаще всего индексы строятся на основе B-деревьев (B-Tree) или хэш-таблиц. Суть в том, что БД создает отдельную компактную структуру данных, где значения нужной колонки заранее отсортированы, а рядом лежат быстрые указатели на физическое расположение строк на диске. ✅ Зачем нужны: * Скорость поиска (SELECT с условием WHERE) возрастает в сотни раз. * Мгновенно ускоряются операции сортировки (ORDER BY) и связывания таблиц (JOIN). ❌ Чем платим (минусы): * Тормоза при записи: при каждом INSERT, UPDATE или DELETE базе приходится перестраивать индекс. * Место на диске: индексы хранятся на диске и съедают оперативную память (RAM). Иногда массивные индексы весят больше, чем сами данные таблицы. 🛠 Чек-лист: индексировать или нет? 🟢 Обязательно индексируем: 1. Колонки, которые постоянно светятся в WHERE, JOIN, ORDER BY, GROUP BY. 2. Внешние ключи (Foreign Keys). Первичные (Primary Keys) СУБД индексирует автоматически. 3. Столбцы с высокой уникальностью значений (ID пользователей, email, артикулы). 🔴 НЕ индексируем: 1. Крошечные таблицы-справочники (прочитать их целиком быстрее, чем дергать индекс). 2. Колонки с низкой уникальностью значений (например, пол или статус active/inactive - индекс по ним практически бесполезен). 3. Таблицы с интенсивной записью (например, логирование). Индексы там убьют производительность INSERT. 💡Не создавай индексы «на всякий случай». Лови медленные запросы, читай вывод EXPLAIN (или EXPLAIN ANALYZE) и добавляй индексы только там, где они реально решают проблему. 📲 Мы в MAX #db 👉 @database_info

🧱 Антипаттерн: Ненормализованная схема в SQL Когда нужно «быстро запилить фичу», руки тянутся сделать одну таблицу, где и за
🧱 Антипаттерн: Ненормализованная схема в SQL Когда нужно «быстро запилить фичу», руки тянутся сделать одну таблицу, где и заказ, и клиент, и товары — всё в куче. Пример:

CREATE TABLE orders (
  order_id SERIAL PRIMARY KEY,
  customer_name TEXT,
  customer_email TEXT,
  product_1_name TEXT,
  product_1_price NUMERIC,
  product_2_name TEXT,
  product_2_price NUMERIC
);
😰 Что пойдет не так: – Дублирование данных — имя клиента повторяется в каждом заказе. – Нет масштабируемости — максимум 2 продукта? А если будет 3? – Трудности с запросами — попробуй посчитать топ-5 товаров. Удачи. – Адские апдейты — изменить email клиента надо во всех заказах. ✅ Как правильно: 1. Нормализуй. Раздели данные на сущности: customers, orders, products, order_items. 2. Используй внешние ключи. 3. Не бойся JOIN'ов — они для этого и придуманы. Пример нормализованной структуры:

-- Таблица клиентов
CREATE TABLE customers (
  id SERIAL PRIMARY KEY,
  name TEXT,
  email TEXT
);

-- Таблица заказов
CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  customer_id INT REFERENCES customers(id)
);

-- Таблица товаров
CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  name TEXT,
  price NUMERIC
);

-- Связка товаров и заказов
CREATE TABLE order_items (
  order_id INT REFERENCES orders(id),
  product_id INT REFERENCES products(id),
  quantity INT
);
📌 Да, нормализация требует чуть больше времени. Зато потом вы не утонете в хаосе. Сохрани, чтобы не забыть — и не повторять чужих ошибок. 📲 Мы в MAX #db 👉 @database_info

🎯 Мини-гайд: как НЕ спроектировать монстра вместо схемы БД Когда проект только начинается, есть соблазн «не заморачиваться»
🎯 Мини-гайд: как НЕ спроектировать монстра вместо схемы БД Когда проект только начинается, есть соблазн «не заморачиваться» и сделать одну большую таблицу на всё. Спойлер: потом будет больно. Вот как этого избежать 👇 1. Начинай с нормализации – Смотри, какие поля повторяются. – Разделяй по сущностям: клиент ≠ заказ ≠ товар. – Нормальные формы — не академикам, а тебе на пользу. 2. Определи связи заранее – Один ко многим? Многие ко многим? – Используй FOREIGN KEY, чтобы база помогала тебе, а не мешала. 3. Не бойся JOIN-ов – Да, их становится больше. – Но это лучше, чем сотни NULL - ов и "status_1", "status_2" в одной колонке. 4. Планируй под рост – Временные костыли становятся постоянными. – Заложи масштабируемость: разнос сущностей, отдельные таблицы для логов, истории, связей. 5. Назначь ID-шки как бог велел – PRIMARY KEY + автоинкремент или UUID. – Не делай email или name ключом — это путь в баги. 🧠 Помни: хорошо спроектированная схема ускоряет разработку, а не тормозит её. А переделывать схему сложнее, чем сделать нормально с самого начала. 📲 Мы в MAX #db 👉 @database_info

🚀 Подборка полезных 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 Типичный Сисадмин https://max.ru/channel_win_sysadmin Системный Администратор Windows https://max.ru/channel_linux_admin Linux: Системный администратор https://max.ru/channel_linuxmod Linux https://max.ru/channel_i_linux Системный администратор https://max.ru/channel_devopslib DevOps, SRE, Sysadmin https://max.ru/channel_devops_star DevOps Star (Звезда Девопса) Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак Английский с нуля 🇬🇧 https://max.ru/UchuEnglish 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С https://max.ru/channel_DevLab1C 1С:Предприятие 8 Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика https://max.ru/channel_cpp_geek C++ geek Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Rust📌 https://max.ru/channel_rust_lib Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика https://max.ru/channel_java_geek Java Geek 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 Обучающие видео, книги по Физике и Математике Вакансии в IT📌 https://max.ru/progjob https://max.ru/channel_rabotait Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Городские📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП https://max.ru/channel_krasnodar_novosty Краснодар Новости https://max.ru/channel_novosibirsk_novosti Новосибирск https://max.ru/channel_samara_novosti Новости Самары https://max.ru/channel_ekaterinburg_novosti Новости Екатеринбурга https://max.ru/channel_kazan_novosti Новости Казани https://max.ru/channel_omsk_novosti Новости Омска https://max.ru/channel_moskva_24 Москва 24

Без каких навыков не обойтись в ИТ прямо сейчас? Разбираемся с одной из самых популярных СУБД среди российских компаний Умени
Без каких навыков не обойтись в ИТ прямо сейчас? Разбираемся с одной из самых популярных СУБД среди российских компаний Умение работать с СУБД PostgreSQL — база, которая точно не будет лишней. В бесплатном курсе от Selectel собрали все необходимое для погружения: от основ реляционной модели до создания таблиц и работы со сложными запросами. Вы актуальную теорию, практические задания и экономию десятков часов на самостоятельных поисках информации. Курс подойдет как для первого знакомства с PostgreSQL, так и чтобы освежить и структурировать знания. Регистрируйтесь и начните обучение бесплатно Реклама. АО "Селектел". erid:2W5zFJmnYQ9

Антипаттерн: «Одна таблица на всё» Когда бизнес-логика усложняется, а структура БД остаётся в духе Excel — жди беды. 🔴 Что э
Антипаттерн: «Одна таблица на всё» Когда бизнес-логика усложняется, а структура БД остаётся в духе Excel — жди беды. 🔴 Что это такое? Проектировщик (часто на раннем этапе) создаёт одну большую таблицу, где: – сотни колонок на все случаи жизни, – куча NULL-ов, – смешаны данные разных сущностей (например, и клиенты, и заказы, и статусы). Так проще… пока не начнётся работа с реальными данными. 💥 Что пойдёт не так: – Производительность падает: индексы не работают эффективно. – Сложность валидации и бизнес-логики. – Трудно расширять: каждое изменение — как операция на открытом сердце. – Нельзя нормально нормализовать: всё связано со всем. ✅ Как избежать: – Используй нормализацию: выноси повторяющиеся и логически независимые данные в отдельные таблицы. – Не бойся JOIN-ов — это не зло, а инструмент. – Планируй схему БД под задачи, а не наоборот. 📌 Пример: Плохо:

CREATE TABLE everything (
  id INT,
  client_name TEXT,
  order_price DECIMAL,
  order_status TEXT,
  delivery_address TEXT,
  ...
);
Хорошо:

CREATE TABLE clients (
  id INT PRIMARY KEY,
  name TEXT
);

CREATE TABLE orders (
  id INT PRIMARY KEY,
  client_id INT REFERENCES clients(id),
  price DECIMAL,
  status TEXT
);
📎 Вывод: одна таблица ≠ проще. Это короткий путь к хаосу. Разделяй и властвуй. Сохрани, чтобы не пришлось рефакторить через полгода 👇 📲 Мы в MAX #db 👉 @database_info

❌ Антипаттерн: Хранить даты и время в VARCHAR Встречали такое? CREATE TABLE orders ( id SERIAL PRIMARY KEY, order_date VARCHA
❌ Антипаттерн: Хранить даты и время в VARCHAR Встречали такое?

CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  order_date VARCHAR(20)
);
На первый взгляд — всё ок: дата есть, строка хранит. Но на практике — сплошные проблемы: 🔴 Нет гарантии формата '2024-12-01', '12/01/2024', '01.12.24', 'вчера' — всё ляжет, но работать с этим потом боль. 🔴 Сложность фильтрации и сортировки Сравнение строк ≠ сравнение дат. Запросы типа WHERE order_date > '2024-01-01' могут вести себя непредсказуемо. 🔴 Нельзя использовать функции времени Ни DATE_TRUNC, ни AGE(), ни агрегаты по времени не работают нормально с VARCHAR. ✅ Как правильно Используйте типы DATE, TIMESTAMP, TIMESTAMPTZ — они: * валидируют данные на вставке; * дают мощный инструментарий для анализа; * упрощают работу с часовыми поясами и интервалами.

CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  order_date TIMESTAMPTZ DEFAULT now()
);
💡 Если данные приходят в виде строк — парси их при загрузке, а не храни как есть. Сохрани, чтобы не наступить на эти же грабли ☝️ А как у вас хранят даты? 📲 Мы в MAX #db 👉 @database_info

🔎 Мини-гайд: Индексы в PostgreSQL — быстро и по делу Индексы — главный инструмент для ускорения запросов. Но неправильное ис
🔎 Мини-гайд: Индексы в PostgreSQL — быстро и по делу Индексы — главный инструмент для ускорения запросов. Но неправильное использование может только навредить. Основные типы индексов в PostgreSQL: - B-tree — по умолчанию. Идеален для поиска по равенству и диапазону (=, <, >, BETWEEN). - Hash — только для поиска по точному равенству (=). Становится актуальным реже. - GIN — для массивов, JSONB, полнотекстового поиска. - GiST — геоданные, поиск по диапазонам, сложные типы. - BRIN — для очень больших таблиц с упорядоченными данными (например, логи). Практические советы: - Не злоупотребляй индексами: каждый индекс замедляет INSERT/UPDATE/DELETE. - Следи за актуальностью: периодически проверяй и удаляй неиспользуемые (pg_stat_user_indexes поможет). - Составные индексы ((col1, col2)) эффективны, только если условия WHERE учитывают порядок колонок. - Используй EXPLAIN ANALYZE, чтобы понять, работает ли индекс в реальности. Типичная ошибка: Создать индекс на всё подряд без анализа запросов. Итог — тормоза на записи и огромный размер базы. ✅ Индексы — это как специи: мало — пресно, много — несъедобно. Вывод: Хотите быструю базу — планируйте индексацию так же внимательно, как сами запросы. Сохрани, чтобы не забыть! 📲 Мы в MAX #db 👉 @database_info