Forwarded from DevOps // Human Help
#bd #ten
Это перевод / адаптация оригинальной статьи
Если понравился пост и считаешь, что я не зря потрудился — ставь реакцию
Показался полезным — добавляй в избранное
Подписывайся на канал DevOps // Human Help
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
VACUUM FULL — когда, зачем и с какими рисками
Сейчас поговорим про одну из самых «страшных» команд в арсенале DBA —
Что делает VACUUM FULL?
Он освобождает табличное пространство, физически удаляя "мертвые" строки и переписывая всю таблицу заново. Это не просто очистка, а именно перезапись. Поэтому:
- Таблица полностью блокируется на запись и чтение.
- Используется временное дисковое пространство (вплоть до размера таблицы).
- Может существенно сократить размер базы — особенно, если давно не было очистки.
Когда применять:
- После массового удаления данных.
- Когда обычный
- При миграции/переезде базы, чтобы максимально уменьшить backup.
Чего опасаться:
- На больших таблицах — это может занять часы.
- Блокировки = пользователи «висят».
- Нужно много свободного места на диске.
Альтернатива: если задача — просто освободить место и база под нагрузкой, рассмотрите
Лично я использую
А вы? Когда последний раз делали
#db
👉 @database_info
Сейчас поговорим про одну из самых «страшных» команд в арсенале DBA —
VACUUM FULL
. Она часто спасает, когда база разрослась до неприличных размеров… но может и «уронить» прод, если запустить не вовремя.Что делает VACUUM FULL?
Он освобождает табличное пространство, физически удаляя "мертвые" строки и переписывая всю таблицу заново. Это не просто очистка, а именно перезапись. Поэтому:
- Таблица полностью блокируется на запись и чтение.
- Используется временное дисковое пространство (вплоть до размера таблицы).
- Может существенно сократить размер базы — особенно, если давно не было очистки.
Когда применять:
- После массового удаления данных.
- Когда обычный
VACUUM
не помогает уменьшить размер базы.- При миграции/переезде базы, чтобы максимально уменьшить backup.
Чего опасаться:
- На больших таблицах — это может занять часы.
- Блокировки = пользователи «висят».
- Нужно много свободного места на диске.
Альтернатива: если задача — просто освободить место и база под нагрузкой, рассмотрите
pg_repack
. Он позволяет делать реорганизацию без блокировок (но требует отдельной установки).Лично я использую
VACUUM FULL
только в окне обслуживания или на read replica.А вы? Когда последний раз делали
VACUUM FULL
?#db
👉 @database_info
🧵 Сегодня я покажу вам простой, но мощный способ отладки сложных SQL-запросов
Когда у вас в проекте появляется монструозный запрос с десятками джойнов, подзапросов и оконных функций — ловить ошибки становится больно. Но есть подход, который реально спасает: инкрементальная отладка.
💡 Суть: разбиваем запрос на небольшие части и поочередно проверяем каждую
Вот как это делаю я:
1. Начинаю с ядра — самого внутреннего подзапроса или CTE. Проверяю, что он возвращает ожидаемые данные.
2. Добавляю следующий уровень логики — джойны, условия, группировки. Каждый раз выполняю и проверяю результат.
3. Для удобства использую
4. Сложные выражения и агрегаты выношу в отдельные CTE — это помогает быстрее изолировать проблему.
5. Если запрос очень тяжёлый — сохраняю промежуточные результаты в временные таблицы.
🔥 PostgreSQL позволяет использовать
Если хотите, могу на неделе разобрать один такой "тяжёлый" запрос от подписчика. Скиньте в комменты 👇
#db
👉 @database_info
Когда у вас в проекте появляется монструозный запрос с десятками джойнов, подзапросов и оконных функций — ловить ошибки становится больно. Но есть подход, который реально спасает: инкрементальная отладка.
💡 Суть: разбиваем запрос на небольшие части и поочередно проверяем каждую
Вот как это делаю я:
1. Начинаю с ядра — самого внутреннего подзапроса или CTE. Проверяю, что он возвращает ожидаемые данные.
2. Добавляю следующий уровень логики — джойны, условия, группировки. Каждый раз выполняю и проверяю результат.
3. Для удобства использую
WITH
(CTE) — это даёт имена промежуточным результатам и делает запрос читабельным.4. Сложные выражения и агрегаты выношу в отдельные CTE — это помогает быстрее изолировать проблему.
5. Если запрос очень тяжёлый — сохраняю промежуточные результаты в временные таблицы.
🔥 PostgreSQL позволяет использовать
EXPLAIN (ANALYZE, BUFFERS)
для профилирования на каждом этапе. Очень помогает найти, где тормозит.Если хотите, могу на неделе разобрать один такой "тяжёлый" запрос от подписчика. Скиньте в комменты 👇
#db
👉 @database_info
Когда речь идет о масштабируемости и высокой доступности данных, особенно важно выбрать надежную СУБД.
⭐️ 17 апреля в 12:00 по МСК эксперты УЦСБ и «Газинформсервис» проведут вебинар «Кластерные решения для больших объемов данных: отечественный опыт», на котором продемонстрируют:
▪️ Как отечественная СУБД обеспечивает высокую доступность данных в условиях высокой нагрузки
▪️ Какими особенностями и преимуществами обладает СУБД Jatoba
▪️ Кейсы успешных внедрений
▪️ Возможности интерфейса и работу по отказоустойчивости Jatoba DB
Вебинар будет полезен:
▪️ Системным администраторам и инженерам, работающим с СУБД и решающим задачи масштабирования и обработки данных
▪️ Руководителям проектов и аналитикам, оптимизирующим процессы работы с данными
▪️ Топ-менеджерам и IT-директорам, заинтересованным в защите данных и повышении эффективности работы с ними
Регистрация
Реклама. ООО «Уральский центр систем безопасности» ИНН 6672235068 Erid: 2Vtzqufy2PC
Вебинар будет полезен:
Регистрация
Реклама. ООО «Уральский центр систем безопасности» ИНН 6672235068 Erid: 2Vtzqufy2PC
Please open Telegram to view this post
VIEW IN TELEGRAM
⚠️ Антипаттерн: использовать NULL без оглядки
На первый взгляд
🔸
🔸 Агрегации ведут себя странно.
🔸 Индексы и
🔸
💡 Как избежать проблем:
1. Всегда осознанно работай с
2. По возможности избегай
3. Добавляй проверки в коде:
4. Понимай, как твоя СУБД работает с
🎯 Вывод:
Сохрани, чтобы не отловить баг на проде 🐛
#db
👉 @database_info
На первый взгляд
NULL
— это просто “нет значения”. Но в реальности — это тихий саботаж:🔸
NULL != NULL
. Да-да, сравнение NULL = NULL
даст false
или unknown
. Это ломает привычную логику и может убить фильтры.🔸 Агрегации ведут себя странно.
COUNT(column)
не считает NULL'ы. AVG
, SUM
— тоже их игнорируют. Итог: неверная статистика.🔸 Индексы и
WHERE column IS NULL
. Не все СУБД эффективно используют индексы при таких запросах. Можно словить тормоза.🔸
NOT IN
+ NULL
= 💥. Запрос WHERE id NOT IN (subquery)
может вернуть пустой результат, если в подзапросе есть хотя бы один NULL
.💡 Как избежать проблем:
1. Всегда осознанно работай с
NULL
— используй IS NULL
и IS NOT NULL
, не =
и !=
.2. По возможности избегай
NULL
в колонках, где это не нужно. Лучше использовать значения по умолчанию.3. Добавляй проверки в коде:
COALESCE
, IFNULL
, NVL
и аналоги.4. Понимай, как твоя СУБД работает с
NULL
в индексах и фильтрах.🎯 Вывод:
NULL
— не пустота, а “неизвестность”. Обращайся с ним осторожно, иначе баги будут неявными и неприятными.Сохрани, чтобы не отловить баг на проде 🐛
#db
👉 @database_info
🎯 Мини-гайд
Транзакции в SQLite: просто, но со своими нюансами
SQLite — это встраиваемая база данных, и она немного отличается от привычных серверных СУБД (PostgreSQL, MySQL) в части работы с транзакциями. Но транзакции там есть, и работают по принципу ACID — атомарность, согласованность, изолированность и долговечность.
Разберёмся по полочкам:
🔹 Как начинается и заканчивается транзакция?
Или, в случае ошибки:
Можно использовать синонимы:
-
-
-
Они отличаются уровнем блокировок.
🔹 Типы транзакций
1. DEFERRED (по умолчанию)
🔒 Блокировки ставятся только при первом доступе к таблице (на чтение/запись).
2. IMMEDIATE
🔒 Сразу ставит блокировку на запись (write-lock). Полезно, если точно знаешь, что будешь писать — исключишь гонки.
3. EXCLUSIVE
🔒 Блокирует БД полностью. Даже другие чтения не пройдут.
🔹 Особенности SQLite
- Одна запись за раз: SQLite поддерживает одновременные чтения, но только одну запись одновременно. Остальные получат "database is locked".
- Авто-коммиты: если явно не начать транзакцию — SQLite будет делать коммит после каждого запроса.
- Журналирование: SQLite использует WAL (write-ahead log) или rollback journal — в зависимости от настроек. WAL — более производителен для параллельного чтения.
💡 Советы
- При пакетной вставке всегда оборачивай в транзакцию:
→ Это в разы быстрее, чем отдельные
- Если получаешь ошибку
- Не оставил ли ты открытые транзакции
- Не работают ли несколько процессов с БД одновременно без координации
💬 Вывод: транзакции в SQLite — простые, но критически важные для производительности и корректности. Даже в одиночной БД нужна дисциплина.
Сохрани, чтобы не потерять!
#db
👉 @database_info
Транзакции в SQLite: просто, но со своими нюансами
SQLite — это встраиваемая база данных, и она немного отличается от привычных серверных СУБД (PostgreSQL, MySQL) в части работы с транзакциями. Но транзакции там есть, и работают по принципу ACID — атомарность, согласованность, изолированность и долговечность.
Разберёмся по полочкам:
🔹 Как начинается и заканчивается транзакция?
BEGIN TRANSACTION;
-- какие-то запросы
COMMIT;
Или, в случае ошибки:
ROLLBACK;
Можно использовать синонимы:
-
BEGIN
= BEGIN DEFERRED
-
BEGIN IMMEDIATE
-
BEGIN EXCLUSIVE
Они отличаются уровнем блокировок.
🔹 Типы транзакций
1. DEFERRED (по умолчанию)
🔒 Блокировки ставятся только при первом доступе к таблице (на чтение/запись).
2. IMMEDIATE
🔒 Сразу ставит блокировку на запись (write-lock). Полезно, если точно знаешь, что будешь писать — исключишь гонки.
3. EXCLUSIVE
🔒 Блокирует БД полностью. Даже другие чтения не пройдут.
🔹 Особенности SQLite
- Одна запись за раз: SQLite поддерживает одновременные чтения, но только одну запись одновременно. Остальные получат "database is locked".
- Авто-коммиты: если явно не начать транзакцию — SQLite будет делать коммит после каждого запроса.
- Журналирование: SQLite использует WAL (write-ahead log) или rollback journal — в зависимости от настроек. WAL — более производителен для параллельного чтения.
💡 Советы
- При пакетной вставке всегда оборачивай в транзакцию:
BEGIN;
INSERT INTO users VALUES (...);
INSERT INTO users VALUES (...);
...
COMMIT;
→ Это в разы быстрее, чем отдельные
INSERT
с автокоммитом.- Если получаешь ошибку
database is locked
, проверь:- Не оставил ли ты открытые транзакции
- Не работают ли несколько процессов с БД одновременно без координации
💬 Вывод: транзакции в SQLite — простые, но критически важные для производительности и корректности. Даже в одиночной БД нужна дисциплина.
Сохрани, чтобы не потерять!
#db
👉 @database_info
🚨 SELECT * - скрытый враг в проде
На dev-сервере всё шустро. В проде — беда: запросы висят, база потеет. И вроде бы всё ок... пока не заглянешь в SQL:
На первый взгляд — удобно. Но:
🔻 Проблемы “SELECT *”:
– Тянет все колонки, даже ненужные. А их может быть 30+.
– Увеличивает нагрузку на сеть и память приложения.
– Ломает кэш — ведь даже малейшие изменения в колонках меняют структуру результата.
– Убивает индекс-only scan: Postgres не может использовать покрывающий индекс, если явно не указаны поля.
✅ Как надо:
🎯 Выбирай только нужные поля:
💡 Хочешь “быстро протестить” в dev-е? Ок. Но не пускай такое в прод. Автоматизируй линтинг SQL, если надо.
Вывод:
Сохрани, чтобы не словить боль в проде.
А у тебя где последний раз встречалось
#db
👉 @database_info
На dev-сервере всё шустро. В проде — беда: запросы висят, база потеет. И вроде бы всё ок... пока не заглянешь в SQL:
SELECT * FROM users WHERE status = 'active';
На первый взгляд — удобно. Но:
🔻 Проблемы “SELECT *”:
– Тянет все колонки, даже ненужные. А их может быть 30+.
– Увеличивает нагрузку на сеть и память приложения.
– Ломает кэш — ведь даже малейшие изменения в колонках меняют структуру результата.
– Убивает индекс-only scan: Postgres не может использовать покрывающий индекс, если явно не указаны поля.
✅ Как надо:
🎯 Выбирай только нужные поля:
SELECT id, name, email FROM users WHERE status = 'active';
💡 Хочешь “быстро протестить” в dev-е? Ок. Но не пускай такое в прод. Автоматизируй линтинг SQL, если надо.
Вывод:
SELECT *
— это не “удобно”, это дорого. И ты за него уже платишь.Сохрани, чтобы не словить боль в проде.
А у тебя где последний раз встречалось
SELECT *
?#db
👉 @database_info
📕Открытый урок о NoSQL с Cassandra для разработчиков, администраторов, специалистов по базам данных, Data engineers, Backend и FullStack-разработчиков.
На открытом уроке 21 апреля в 20:00 мск мы погрузимся в тонкости работы c NoSQL в Cassandra.
📗В результате вы:
- Узнаете, как работает Cassandra и какие есть особенности про которые никто говорит;
- Разберетесь, как избежать и решать проблемы в работе Сassandra;
- Освоите техники и лайфхаки в Сassandra на практике.
Спикер Дмитрий Гурьянов — Team Lead команды разработки CRM-решений на платформе .NET в Промсвязьбанке, 9+ лет в разработке, работал в Microsoft над продуктом Bing, аспирант кафедры "Системы обработки информации и управления" в МГТУ им. Н.Э. Баумана.
👉Регистрируйтесь прямо сейчас, чтобы не пропустить мероприятие: https://vk.cc/cKWZYo
📙Все участники открытого урока получат скидку на курс "Базы данных"
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
На открытом уроке 21 апреля в 20:00 мск мы погрузимся в тонкости работы c NoSQL в Cassandra.
📗В результате вы:
- Узнаете, как работает Cassandra и какие есть особенности про которые никто говорит;
- Разберетесь, как избежать и решать проблемы в работе Сassandra;
- Освоите техники и лайфхаки в Сassandra на практике.
Спикер Дмитрий Гурьянов — Team Lead команды разработки CRM-решений на платформе .NET в Промсвязьбанке, 9+ лет в разработке, работал в Microsoft над продуктом Bing, аспирант кафедры "Системы обработки информации и управления" в МГТУ им. Н.Э. Баумана.
👉Регистрируйтесь прямо сейчас, чтобы не пропустить мероприятие: https://vk.cc/cKWZYo
📙Все участники открытого урока получат скидку на курс "Базы данных"
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Антипаттерн: NULL в WHERE — и ты в ловушке
Когда в таблице есть
Ты ожидаешь, что выберутся все, кто не 30.
Но если
Почему? Потому что
А SQL возвращает строки только там, где
Как избежать?
1. Будь явно осторожен с NULL:
2. Логика на уровне схемы:
– Если поле нужно всегда — делай
– Если допускаешь
3. Не верь глазам своим:
Даже
Вывод:
Это "мы не знаем". И SQL ведёт себя с ним очень осторожно.
Сохрани, чтобы не словить грабли.
#db
👉 @database_info
Когда в таблице есть
NULL
, а в WHERE
ты пишешь что-то вроде:
SELECT * FROM users WHERE age != 30;
Ты ожидаешь, что выберутся все, кто не 30.
Но если
age IS NULL
— такие строки пропадут из выборки!Почему? Потому что
NULL != 30
не TRUE
, это UNKNOWN
. А SQL возвращает строки только там, где
WHERE
→ TRUE
.Как избежать?
1. Будь явно осторожен с NULL:
SELECT * FROM users
WHERE age != 30 OR age IS NULL;
2. Логика на уровне схемы:
– Если поле нужно всегда — делай
NOT NULL
. – Если допускаешь
NULL
, продумывай поведение выборок.3. Не верь глазам своим:
Даже
count(*)
и count(column)
ведут себя по-разному из-за NULL
.Вывод:
NULL
— это не ноль, не пустая строка и не "ничего". Это "мы не знаем". И SQL ведёт себя с ним очень осторожно.
Сохрани, чтобы не словить грабли.
#db
👉 @database_info
🚨 Как понять, почему запрос тормозит?
Сегодня покажу простой, но действенный подход к диагностике медленных SQL-запросов. Когда к тебе приходит прод с жалобой "что-то всё виснет", важно не паниковать, а системно подойти к анализу.
Вот что я делаю первым делом:
1. Включаю
Это ваш лучший друг. Не
2. Смотрю на узлы с наибольшим временем
Часто виновник — Seq Scan по большой таблице или Nested Loop с миллионами итераций.
3. Ищу несработавшие индексы
Был ли
4. Проверяю фильтрацию и сортировку
ORDER BY может убить всё. Особенно если не по индексу.
5. Думаю про статистику
🛠 Если ты часто отлаживаешь SQL — советую поставить pgMustard или использовать EXPLAIN DEPOT. Они визуализируют планы и сразу показывают узкие места.
💬 Расскажи, как ты ищешь узкие места в запросах? Есть свой лайфхак?
#db
👉 @database_info
Сегодня покажу простой, но действенный подход к диагностике медленных SQL-запросов. Когда к тебе приходит прод с жалобой "что-то всё виснет", важно не паниковать, а системно подойти к анализу.
Вот что я делаю первым делом:
1. Включаю
EXPLAIN (ANALYZE)
Это ваш лучший друг. Не
EXPLAIN
, а именно ANALYZE
, чтобы получить реальные значения времени, а не план на бумаге.2. Смотрю на узлы с наибольшим временем
Часто виновник — Seq Scan по большой таблице или Nested Loop с миллионами итераций.
3. Ищу несработавшие индексы
Был ли
Index Scan
или Index Only Scan
? Если нет — стоит проверить, почему не сработал индекс. Может, фильтр не селективный?4. Проверяю фильтрацию и сортировку
ORDER BY может убить всё. Особенно если не по индексу.
5. Думаю про статистику
ANALYZE
делали недавно? PostgreSQL может строить плохой план, если у него устаревшие данные. 🛠 Если ты часто отлаживаешь SQL — советую поставить pgMustard или использовать EXPLAIN DEPOT. Они визуализируют планы и сразу показывают узкие места.
💬 Расскажи, как ты ищешь узкие места в запросах? Есть свой лайфхак?
#db
👉 @database_info
🚀 Сегодня я покажу вам один из моих любимых хаков для PostgreSQL – генерация серий дат без циклов и хранимок. Это идеальный способ быстро собрать таймлайн для аналитики или отчётов.
Сценарий: вам нужно построить список всех дат за последний месяц — например, чтобы потом сделать LEFT JOIN к таблице с событиями и увидеть, где были пропуски.
Вот как это делается с помощью
💡 Результат — 31 строка с датами от 30 дней назад до сегодняшнего дня.
Теперь добавим, например, LEFT JOIN к таблице
📊 Отлично подходит для дашбордов, когда нужно увидеть, где были дни без событий.
Пользуетесь ли вы
#db
👉 @database_info
Сценарий: вам нужно построить список всех дат за последний месяц — например, чтобы потом сделать LEFT JOIN к таблице с событиями и увидеть, где были пропуски.
Вот как это делается с помощью
generate_series
:
SELECT generate_series(
date_trunc('day', current_date) - interval '30 days',
date_trunc('day', current_date),
interval '1 day'
) AS day;
💡 Результат — 31 строка с датами от 30 дней назад до сегодняшнего дня.
Теперь добавим, например, LEFT JOIN к таблице
events
, чтобы увидеть активность по дням:
SELECT
d.day,
COUNT(e.id) AS events_count
FROM
generate_series(
date_trunc('day', current_date) - interval '30 days',
date_trunc('day', current_date),
interval '1 day'
) AS d(day)
LEFT JOIN events e ON date_trunc('day', e.created_at) = d.day
GROUP BY d.day
ORDER BY d.day;
📊 Отлично подходит для дашбордов, когда нужно увидеть, где были дни без событий.
Пользуетесь ли вы
generate_series
? А может быть, используете что-то подобное в других СУБД? Делитесь в комментариях👇#db
👉 @database_info
🚀 Подборка Telegram каналов для программистов
Системное администрирование, DevOps 📌
https://www.tg-me.com/bash_srv Bash Советы
https://www.tg-me.com/win_sysadmin Системный Администратор Windows
https://www.tg-me.com/sysadmin_girl Девочка Сисадмин
https://www.tg-me.com/srv_admin_linux Админские угодья
https://www.tg-me.com/linux_srv Типичный Сисадмин
https://www.tg-me.com/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://www.tg-me.com/linux_odmin Linux: Системный администратор
https://www.tg-me.com/devops_star DevOps Star (Звезда Девопса)
https://www.tg-me.com/i_linux Системный администратор
https://www.tg-me.com/linuxchmod Linux
https://www.tg-me.com/sys_adminos Системный Администратор
https://www.tg-me.com/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://www.tg-me.com/sysadminof Книги для админов, полезные материалы
https://www.tg-me.com/i_odmin Все для системного администратора
https://www.tg-me.com/i_odmin_book Библиотека Системного Администратора
https://www.tg-me.com/i_odmin_chat Чат системных администраторов
https://www.tg-me.com/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://www.tg-me.com/sysadminoff Новости Линукс Linux
1C разработка 📌
https://www.tg-me.com/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://www.tg-me.com/DevLab1C 1С:Предприятие 8
https://www.tg-me.com/razrab_1C 1C Разработчик
https://www.tg-me.com/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://www.tg-me.com/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://www.tg-me.com/cpp_lib Библиотека C/C++ разработчика
https://www.tg-me.com/cpp_knigi Книги для программистов C/C++
https://www.tg-me.com/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://www.tg-me.com/pythonofff Python академия.
https://www.tg-me.com/BookPython Библиотека Python разработчика
https://www.tg-me.com/python_real Python подборки на русском и английском
https://www.tg-me.com/python_360 Книги по Python
Java разработка 📌
https://www.tg-me.com/BookJava Библиотека Java разработчика
https://www.tg-me.com/java_360 Книги по Java Rus
https://www.tg-me.com/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://www.tg-me.com/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://www.tg-me.com/telegram/com.database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://www.tg-me.com/developer_mobila Мобильная разработка
https://www.tg-me.com/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://www.tg-me.com/frontend_1 Подборки для frontend разработчиков
https://www.tg-me.com/frontend_sovet Frontend советы, примеры и практика!
https://www.tg-me.com/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://www.tg-me.com/game_devv Все о разработке игр
Библиотеки 📌
https://www.tg-me.com/book_for_dev Книги для программистов Rus
https://www.tg-me.com/programmist_of Книги по программированию
https://www.tg-me.com/proglb Библиотека программиста
https://www.tg-me.com/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://www.tg-me.com/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://www.tg-me.com/bookflow Лекции, видеоуроки, доклады с IT конференций
https://www.tg-me.com/rust_lib Полезный контент по программированию на Rust
https://www.tg-me.com/golang_lib Библиотека Go (Golang) разработчика
https://www.tg-me.com/itmozg Программисты, дизайнеры, новости из мира IT
https://www.tg-me.com/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://www.tg-me.com/nodejs_lib Подборки по Node js и все что с ним связано
https://www.tg-me.com/ruby_lib Библиотека Ruby программиста
https://www.tg-me.com/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://www.tg-me.com/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://www.tg-me.com/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://www.tg-me.com/thehaking Канал о кибербезопасности
https://www.tg-me.com/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://www.tg-me.com/ux_web Статьи, книги для дизайнеров
Математика 📌
https://www.tg-me.com/Pomatematike Канал по математике
https://www.tg-me.com/phis_mat Обучающие видео, книги по Физике и Математике
https://www.tg-me.com/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://www.tg-me.com/Excel_lifehack
https://www.tg-me.com/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://www.tg-me.com/sysadmin_rabota Системный Администратор
https://www.tg-me.com/progjob Вакансии в IT
Системное администрирование, DevOps 📌
https://www.tg-me.com/bash_srv Bash Советы
https://www.tg-me.com/win_sysadmin Системный Администратор Windows
https://www.tg-me.com/sysadmin_girl Девочка Сисадмин
https://www.tg-me.com/srv_admin_linux Админские угодья
https://www.tg-me.com/linux_srv Типичный Сисадмин
https://www.tg-me.com/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://www.tg-me.com/linux_odmin Linux: Системный администратор
https://www.tg-me.com/devops_star DevOps Star (Звезда Девопса)
https://www.tg-me.com/i_linux Системный администратор
https://www.tg-me.com/linuxchmod Linux
https://www.tg-me.com/sys_adminos Системный Администратор
https://www.tg-me.com/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://www.tg-me.com/sysadminof Книги для админов, полезные материалы
https://www.tg-me.com/i_odmin Все для системного администратора
https://www.tg-me.com/i_odmin_book Библиотека Системного Администратора
https://www.tg-me.com/i_odmin_chat Чат системных администраторов
https://www.tg-me.com/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://www.tg-me.com/sysadminoff Новости Линукс Linux
1C разработка 📌
https://www.tg-me.com/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://www.tg-me.com/DevLab1C 1С:Предприятие 8
https://www.tg-me.com/razrab_1C 1C Разработчик
https://www.tg-me.com/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://www.tg-me.com/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://www.tg-me.com/cpp_lib Библиотека C/C++ разработчика
https://www.tg-me.com/cpp_knigi Книги для программистов C/C++
https://www.tg-me.com/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://www.tg-me.com/pythonofff Python академия.
https://www.tg-me.com/BookPython Библиотека Python разработчика
https://www.tg-me.com/python_real Python подборки на русском и английском
https://www.tg-me.com/python_360 Книги по Python
Java разработка 📌
https://www.tg-me.com/BookJava Библиотека Java разработчика
https://www.tg-me.com/java_360 Книги по Java Rus
https://www.tg-me.com/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://www.tg-me.com/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://www.tg-me.com/telegram/com.database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://www.tg-me.com/developer_mobila Мобильная разработка
https://www.tg-me.com/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://www.tg-me.com/frontend_1 Подборки для frontend разработчиков
https://www.tg-me.com/frontend_sovet Frontend советы, примеры и практика!
https://www.tg-me.com/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://www.tg-me.com/game_devv Все о разработке игр
Библиотеки 📌
https://www.tg-me.com/book_for_dev Книги для программистов Rus
https://www.tg-me.com/programmist_of Книги по программированию
https://www.tg-me.com/proglb Библиотека программиста
https://www.tg-me.com/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://www.tg-me.com/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://www.tg-me.com/bookflow Лекции, видеоуроки, доклады с IT конференций
https://www.tg-me.com/rust_lib Полезный контент по программированию на Rust
https://www.tg-me.com/golang_lib Библиотека Go (Golang) разработчика
https://www.tg-me.com/itmozg Программисты, дизайнеры, новости из мира IT
https://www.tg-me.com/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://www.tg-me.com/nodejs_lib Подборки по Node js и все что с ним связано
https://www.tg-me.com/ruby_lib Библиотека Ruby программиста
https://www.tg-me.com/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://www.tg-me.com/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://www.tg-me.com/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://www.tg-me.com/thehaking Канал о кибербезопасности
https://www.tg-me.com/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://www.tg-me.com/ux_web Статьи, книги для дизайнеров
Математика 📌
https://www.tg-me.com/Pomatematike Канал по математике
https://www.tg-me.com/phis_mat Обучающие видео, книги по Физике и Математике
https://www.tg-me.com/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://www.tg-me.com/Excel_lifehack
https://www.tg-me.com/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://www.tg-me.com/sysadmin_rabota Системный Администратор
https://www.tg-me.com/progjob Вакансии в IT
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
💻 Прокачивай терминал вместе с нами! 👇
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
💻 Прокачивай терминал вместе с нами! 👇
Сегодня я хочу рассказать вам про одну часто недооцененную фишку в PostgreSQL — partial indexes (частичные индексы).
Обычно мы создаём индексы на всю таблицу, но что если нам нужно ускорить только небольшую часть данных? Например, часто выбираются только активные пользователи (
Что это даёт:
- Индекс меньше по размеру → быстрее поиск и обновление.
- Используется только тогда, когда запрос соответствует условию
- Меньше нагрузка на диск при обновлениях таблицы.
🛠 Где это реально помогает:
- Таблицы с миллионами записей, где активно работают только с частью строк.
- Сценарии "горячих" и "холодных" данных.
Рекомендую попробовать partial indexes там, где обычные индексы слишком тяжелы или тормозят обновления!
#db
👉 @database_info
Обычно мы создаём индексы на всю таблицу, но что если нам нужно ускорить только небольшую часть данных? Например, часто выбираются только активные пользователи (
status
= 'active'
). Вместо полного индекса можно создать индекс только для нужного поднабора данных:
CREATE INDEX idx_active_users
ON users (last_login)
WHERE status = 'active';
Что это даёт:
- Индекс меньше по размеру → быстрее поиск и обновление.
- Используется только тогда, когда запрос соответствует условию
status = 'active'
.- Меньше нагрузка на диск при обновлениях таблицы.
🛠 Где это реально помогает:
- Таблицы с миллионами записей, где активно работают только с частью строк.
- Сценарии "горячих" и "холодных" данных.
Рекомендую попробовать partial indexes там, где обычные индексы слишком тяжелы или тормозят обновления!
#db
👉 @database_info
🔎 Мини-гайд: Индексы в PostgreSQL — быстро и по делу
Индексы — главный инструмент для ускорения запросов. Но неправильное использование может только навредить.
Основные типы индексов в PostgreSQL:
-
-
-
-
-
Практические советы:
- Не злоупотребляй индексами: каждый индекс замедляет
- Следи за актуальностью: периодически проверяй и удаляй неиспользуемые (
- Составные индексы (
- Используй
Типичная ошибка:
Создать индекс на всё подряд без анализа запросов. Итог — тормоза на записи и огромный размер базы.
✅ Индексы — это как специи: мало — пресно, много — несъедобно.
Вывод:
Хотите быструю базу — планируйте индексацию так же внимательно, как сами запросы.
Сохрани, чтобы не забыть!
#db
👉 @database_info
Индексы — главный инструмент для ускорения запросов. Но неправильное использование может только навредить.
Основные типы индексов в PostgreSQL:
-
B-tree
— по умолчанию. Идеален для поиска по равенству и диапазону (=
, <
, >
, BETWEEN
).-
Hash
— только для поиска по точному равенству (=
). Становится актуальным реже.-
GIN
— для массивов, JSONB, полнотекстового поиска.-
GiST
— геоданные, поиск по диапазонам, сложные типы.-
BRIN
— для очень больших таблиц с упорядоченными данными (например, логи).Практические советы:
- Не злоупотребляй индексами: каждый индекс замедляет
INSERT/UPDATE/DELETE
.- Следи за актуальностью: периодически проверяй и удаляй неиспользуемые (
pg_stat_user_indexes
поможет).- Составные индексы (
(col1, col2)
) эффективны, только если условия WHERE учитывают порядок колонок.- Используй
EXPLAIN ANALYZE
, чтобы понять, работает ли индекс в реальности.Типичная ошибка:
Создать индекс на всё подряд без анализа запросов. Итог — тормоза на записи и огромный размер базы.
✅ Индексы — это как специи: мало — пресно, много — несъедобно.
Вывод:
Хотите быструю базу — планируйте индексацию так же внимательно, как сами запросы.
Сохрани, чтобы не забыть!
#db
👉 @database_info
❌ Антипаттерн: Хранить даты и время в
Встречали такое?
На первый взгляд — всё ок: дата есть, строка хранит. Но на практике — сплошные проблемы:
🔴 Нет гарантии формата
🔴 Сложность фильтрации и сортировки
Сравнение строк ≠ сравнение дат.
Запросы типа
🔴 Нельзя использовать функции времени
Ни
✅ Как правильно
Используйте типы
* валидируют данные на вставке;
* дают мощный инструментарий для анализа;
* упрощают работу с часовыми поясами и интервалами.
💡 Если данные приходят в виде строк — парси их при загрузке, а не храни как есть.
Сохрани, чтобы не наступить на эти же грабли ☝️
А как у вас хранят даты?
#db
👉 @database_info
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()
);
💡 Если данные приходят в виде строк — парси их при загрузке, а не храни как есть.
Сохрани, чтобы не наступить на эти же грабли ☝️
А как у вас хранят даты?
#db
👉 @database_info
📕MySQL для администраторов, разработчиков, архитекторов и специалистов баз данных
Как грамотно оптимизировать производительность в MySQL и решить возникающие проблемы.
📗 На вебинаре 6 мая в 19:00 разберём:
1. Практические методы оптимизации производительности, диагностику нагрузки и анализ "узких мест" MySQL;
2. Оптимизацию запросов: от простых до сложных.
📘 В результате будете знать всё о настройке ключевых параметров конфигурации, уметь самостоятельно диагностировать и решать проблемы производительности MySQL.
👉 Регистрация и подробности о курсе Базы данных: https://vk.cc/cLzQgf
Все участники открытого урока получат скидку на курс
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Как грамотно оптимизировать производительность в MySQL и решить возникающие проблемы.
📗 На вебинаре 6 мая в 19:00 разберём:
1. Практические методы оптимизации производительности, диагностику нагрузки и анализ "узких мест" MySQL;
2. Оптимизацию запросов: от простых до сложных.
📘 В результате будете знать всё о настройке ключевых параметров конфигурации, уметь самостоятельно диагностировать и решать проблемы производительности MySQL.
👉 Регистрация и подробности о курсе Базы данных: https://vk.cc/cLzQgf
Все участники открытого урока получат скидку на курс
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Антипаттерн: «Одна таблица на всё»
Когда бизнес-логика усложняется, а структура БД остаётся в духе Excel — жди беды.
🔴 Что это такое?
Проектировщик (часто на раннем этапе) создаёт одну большую таблицу, где:
– сотни колонок на все случаи жизни,
– куча
– смешаны данные разных сущностей (например, и клиенты, и заказы, и статусы).
Так проще… пока не начнётся работа с реальными данными.
💥 Что пойдёт не так:
– Производительность падает: индексы не работают эффективно.
– Сложность валидации и бизнес-логики.
– Трудно расширять: каждое изменение — как операция на открытом сердце.
– Нельзя нормально нормализовать: всё связано со всем.
✅ Как избежать:
– Используй нормализацию: выноси повторяющиеся и логически независимые данные в отдельные таблицы.
– Не бойся JOIN-ов — это не зло, а инструмент.
– Планируй схему БД под задачи, а не наоборот.
📌 Пример:
Плохо:
Хорошо:
📎 Вывод: одна таблица ≠ проще. Это короткий путь к хаосу.
Разделяй и властвуй.
Сохрани, чтобы не пришлось рефакторить через полгода 👇
#db
👉 @database_info
Когда бизнес-логика усложняется, а структура БД остаётся в духе 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
);
📎 Вывод: одна таблица ≠ проще. Это короткий путь к хаосу.
Разделяй и властвуй.
Сохрани, чтобы не пришлось рефакторить через полгода 👇
#db
👉 @database_info
🎯 Мини-гайд: как НЕ спроектировать монстра вместо схемы БД
Когда проект только начинается, есть соблазн «не заморачиваться» и сделать одну большую таблицу на всё.
Спойлер: потом будет больно.
Вот как этого избежать 👇
1. Начинай с нормализации
– Смотри, какие поля повторяются.
– Разделяй по сущностям: клиент ≠ заказ ≠ товар.
– Нормальные формы — не академикам, а тебе на пользу.
2. Определи связи заранее
– Один ко многим? Многие ко многим?
– Используй
3. Не бойся JOIN-ов
– Да, их становится больше.
– Но это лучше, чем сотни
4. Планируй под рост
– Временные костыли становятся постоянными.
– Заложи масштабируемость: разнос сущностей, отдельные таблицы для логов, истории, связей.
5. Назначь ID-шки как бог велел
–
– Не делай
🧠 Помни: хорошо спроектированная схема ускоряет разработку, а не тормозит её.
А переделывать схему сложнее, чем сделать нормально с самого начала.
💬 Как ты подходишь к проектированию схемы?
#db
👉 @database_info
Когда проект только начинается, есть соблазн «не заморачиваться» и сделать одну большую таблицу на всё.
Спойлер: потом будет больно.
Вот как этого избежать 👇
1. Начинай с нормализации
– Смотри, какие поля повторяются.
– Разделяй по сущностям: клиент ≠ заказ ≠ товар.
– Нормальные формы — не академикам, а тебе на пользу.
2. Определи связи заранее
– Один ко многим? Многие ко многим?
– Используй
FOREIGN KEY
, чтобы база помогала тебе, а не мешала.3. Не бойся JOIN-ов
– Да, их становится больше.
– Но это лучше, чем сотни
NULL
- ов и "status_1", "status_2" в одной колонке.4. Планируй под рост
– Временные костыли становятся постоянными.
– Заложи масштабируемость: разнос сущностей, отдельные таблицы для логов, истории, связей.
5. Назначь ID-шки как бог велел
–
PRIMARY KEY
+ автоинкремент или UUID.– Не делай
email
или name
ключом — это путь в баги.🧠 Помни: хорошо спроектированная схема ускоряет разработку, а не тормозит её.
А переделывать схему сложнее, чем сделать нормально с самого начала.
💬 Как ты подходишь к проектированию схемы?
#db
👉 @database_info
🔗 Мини-гайд по JOIN-ам в SQL
🔸 INNER JOIN
Что делает: оставляет только совпадающие строки из обеих таблиц.
Когда использовать: когда нужны только те записи, у которых есть соответствие.
🧠 Best practice: это дефолтный выбор. Работает быстрее, т.к. отбрасывает всё "лишнее".
🔸 LEFT JOIN
Что делает: возвращает все строки из левой таблицы и
Когда использовать: когда нужно сохранить всё из первой таблицы, даже если во второй нет данных.
🧠 Часто используется для аналитики: "у каких клиентов не было заказов?"
🔸 RIGHT JOIN
Что делает: наоборот — всё из правой таблицы и
Когда использовать: аналогично
🔸 FULL OUTER JOIN
Что делает: объединяет
Когда использовать: когда важны все данные, даже без соответствий.
🧠 Подходит для reconciliation'а или сверки.
❗ Совет
Фильтры (
Используй
Сохрани, чтобы не забыть. А ты какой JOIN используешь чаще всего?
#db
👉 @database_info
JOIN
— мощнейший инструмент в арсенале SQL. Но многие путаются в типах. Разбираем на пальцах:🔸 INNER JOIN
Что делает: оставляет только совпадающие строки из обеих таблиц.
Когда использовать: когда нужны только те записи, у которых есть соответствие.
SELECT *
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;
🧠 Best practice: это дефолтный выбор. Работает быстрее, т.к. отбрасывает всё "лишнее".
🔸 LEFT JOIN
Что делает: возвращает все строки из левой таблицы и
NULL
из правой, если нет совпадения.Когда использовать: когда нужно сохранить всё из первой таблицы, даже если во второй нет данных.
SELECT *
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
🧠 Часто используется для аналитики: "у каких клиентов не было заказов?"
🔸 RIGHT JOIN
Что делает: наоборот — всё из правой таблицы и
NULL
из левой, если нет совпадения.Когда использовать: аналогично
LEFT JOIN
, но редко встречается, потому что просто меняем порядок таблиц.🔸 FULL OUTER JOIN
Что делает: объединяет
LEFT
и RIGHT
— берёт всё из обеих таблиц.Когда использовать: когда важны все данные, даже без соответствий.
SELECT *
FROM table_a
FULL OUTER JOIN table_b ON table_a.id = table_b.id;
🧠 Подходит для reconciliation'а или сверки.
❗ Совет
Фильтры (
WHERE
) после LEFT JOIN
могут не дать ожидаемый результат.Используй
ON
для условий соединения, WHERE
— для фильтрации результата.Сохрани, чтобы не забыть. А ты какой JOIN используешь чаще всего?
#db
👉 @database_info
🧱 Антипаттерн: Ненормализованная схема в SQL
Когда нужно «быстро запилить фичу», руки тянутся сделать одну таблицу, где и заказ, и клиент, и товары — всё в куче.
Пример:
😰 Что пойдет не так:
– Дублирование данных — имя клиента повторяется в каждом заказе.
– Нет масштабируемости — максимум 2 продукта? А если будет 3?
– Трудности с запросами — попробуй посчитать топ-5 товаров. Удачи.
– Адские апдейты — изменить email клиента надо во всех заказах.
✅ Как правильно:
1. Нормализуй. Раздели данные на сущности:
2. Используй внешние ключи.
3. Не бойся JOIN'ов — они для этого и придуманы.
Пример нормализованной структуры:
📌 Да, нормализация требует чуть больше времени. Зато потом вы не утонете в хаосе.
Сохрани, чтобы не забыть — и не повторять чужих ошибок.
#db
👉 @database_info
Когда нужно «быстро запилить фичу», руки тянутся сделать одну таблицу, где и заказ, и клиент, и товары — всё в куче.
Пример:
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
);
📌 Да, нормализация требует чуть больше времени. Зато потом вы не утонете в хаосе.
Сохрани, чтобы не забыть — и не повторять чужих ошибок.
#db
👉 @database_info