Аналіз спільної Mongo-бази

stack-goldenGET /golden/debug/db-analysis (src/golden/debug/db-analysis.ts) — знімок здоров’я спільної бази stack, яку юзають усі бек-сервіси.

Що це. Усі бек-сервіси (stack, golden, prime, udate, chathouse, academy, ai) пишуть в одну Mongo-базу stack. Read-only debug-ендпоінт (@ApiRoles([director])) знімає метрики колекцій/індексів. Назви колекцій — як у БД; призначення кожної тут не розшифровуємо (див. реєстр сутностей сервісів).

Дві природи даних — звідки що валідне

ДаніВалідний запускЧому
невикористані індекси (ops/since), фрагментація (reusableBytes)прод ?docScan=offruntime-лічильники у пам’яті mongod, у дамп не потрапляють
розміри, кількість, дублікати/надлишкові індекси, max doc sizeлокально на свіжому дампі ?docScan=fullповний скан безпечний; точніше

⚠️ $indexStats рахує з моменту рестарту mongod. У прод-знімку аптайм ~9.85 дня (since ≈ 2026-06-03), тож «0 ops» — надійний сигнал «не юзається». На свіжому дампі лічильники порожні — там «unused» це шум (підтверджено: локальний прогін дав ~200 «unused», прод — лише ~90).

Знімки

ПродЛокальний дамп
Дата2026-06-132026-06-13
Mongo7.0.128.2.3
Аптайм~9.85 дня— (свіжий)
Колекцій / індексів225 / 479226 / 481
dataSize23.5 GB23.1 GB
storageSize9.80 GB6.19 GB
indexSize3.18 GB1.63 GB
totalSize12.98 GB7.82 GB
documents45.5 млн43.8 млн

Одиниці — десяткові MB/GB (bytes ÷ 10⁶), як показує Compass. Не MiB.

Дані майже однакові (23.5 vs 23.1 GB), а займане місце відрізняється на ~5.2 GB. Уся ця різниця — фрагментація на проді (storage +3.6 GB, index +1.55 GB). На свіжому дампі вона зникає → це верхня оцінка того, що поверне compact/resync.

Якщо звіряєш із Compass: локальний Compass (Docker > stack) = колонка «Локальний дамп». Прод-топи фрагментації (нижче) там НЕ видно — на дампі ці колекції крихітні (напр. prime_task_completed_or_canceleds у Compass 28.67 kB, на проді 924 MB). Саме ця різниця — суть аналізу.


🔴 №1 проблема: фрагментація прода (~5 GB реюзабельні)

reusableBytes = місце, виділене WiredTiger, але порожнє (наслідок масових delete/update). Це прод-онлі; у локальному Compass цих роздутих storage нема — там та сама колекція займає стільки, скільки даних. Топ за обсягом сміття (прод, MB):

Колекціяstorage продданіреюзабельно%storage на дампі
academy_answers1038.57 MB68.35 MB966.19 MB93%33.74 MB
prime_task_completed_or_canceleds923.91 MB34.83 KB922.78 MB99.9%28.67 KB
golden_history_sending_mails766.88 MB650.48 MB573.92 MB75%182.52 MB
golden_history_sending_messages210.22 MB429.30 MB117.78 MB56%32.29 MB
statusworkeronudateladyonoperators116.04 MB41.42 MB96.81 MB83%10.96 MB
golden_electron_logs107.00 MB39.80 MB94.72 MB89%10.92 MB
golden_man_profiles98.76 MB20.92 MB89.21 MB90%6.60 MB
golden_tasks21.79 MB425 KB21.30 MB98%110 KB

Колонка «на дампі» показує реальний розмір після стиснення — різниця і є те, що поверне compact.

Плюс роздуті індекси: golden_history_sending_mails має 919.68 MB індексів на проді проти 221.09 MB на дампі (×4). Тобто ця одна колекція — ~1.7 GB на проді, реально потрібно ~400 MB.

Що з цим (перевірити):

  • academy_answers і prime_task_completed_or_canceleds — величезний churn (записи створюються й видаляються). TODO: перевірити чи є сенс у TTL / архівації, і запустити compact.
  • prime_task_completed_or_canceleds — окремо показовий: 365 живих доків, 34 KB даних, але 881 MB storage + 69 MB індексів, усі 5 вторинних індексів з 0 ops. Кандидат №1: дроп невикористаних індексів + compact ≈ зекономить ~950 MB.

🟡 Невикористані індекси (ПРОД, 0 ops за ~10 днів)

~90 індексів з 0 операцій. Сортовано за розміром (топ — найбільша економія місця + пришвидшення запису). TODO-нюанс: перед дропом ще раз звірити since з аптаймом після можливих рестартів.

КолекціяІндексРозмірops
golden_history_sending_messagesladyId_api_1_manId_api_1_timestamp_1_initiatorType_1135.86 MB0
prime_favorite_actionsladyId_1_manId_1_messageId_129.42 MB0
golden_history_sending_messagestimestamp_128.41 MB0
golden_statistics_relationsdate_1_operatorId_1_ladyId_1_final_126.86 MB0
prime_task_completed_or_canceledsidDialog_118.99 MB0
golden_history_sending_messagesladyId_api_116.76 MB0
prime_task_completed_or_canceledscanceled.status_19.21 MB0
golden_operators_activitiesstartActive_1_stopActive_15.55 MB0
chathouse_action_operatorstasks.ladyDbId_1_tasks.config.type_13.50 MB0
udate_counter_messages_menmanUlid_11.34 MB0
prime_favorite_newsstackTopManagerId_11.21 MB0

Решта — десятки індексів по 20–800 KB (email_messages 13 невикористаних, *_admins.email_1, *-supervisors.email_1, user-*-families.* тощо). email_messages має 15 індексів, з них ~13 з 0 ops (many-indexes + has-unused-index).

ai_notes (порожня) має 3 індекси сумарно ~2.4 MiB — реліктові, колекція без даних.

Надлишкові префіксні індекси (структурні)

Індекс є строгим префіксом іншого складеного → запити покриває довший, короткий зайвий. ~20 на проді:

КолекціяЗайвийПокритий
golden_action_operatorsyearMonthDay_1yearMonthDay_1_tasks.ladyId_api_1
chathouse_action_operatorsoperatorFamilyId_1operatorFamilyId_1_supervisorFamilyId_1_yearMonthDay_1
golden_online_timesoperatorFamilyId_1operatorFamilyId_1_date_1
golden_history_sending_messagesoperatorFamilyId_1, ladyId_api_1*_timestamp_1 варіанти
golden_statistics_relationsdate_1, date_1_operatorId_1date_1_operatorId_1_ladyId_1_final_1
golden_favorites, golden_send_mail_historiesladyId_api_1ladyId_api_1_manId_api_1
golden_lady_online, golden_stream_timesoperatorFamilyId_1operatorFamilyId_1_date_1
udate_operators_activitiesoperator_1operator_1_stopActive_1_autocreated
monitoring_logsvpsId_1vpsId_1_nameMicroservice_1_message_1_level_1_createdAt_-1
email_messagesladyStackId_1, manEmail_1, dialogId_1, emailAccountId_1, threadId_1відповідні складені
lady_emailsstackLadyId_1stackLadyId_1_email_1
ai_notesladyId_1ladyId_1_manId_1

Нюанс: деякі з них юзаються (ops>0, напр. golden_online_times.operatorFamilyId_1 — 1238 ops), але складений покриває ті ж запити. Дроп можливий, але звірити плани запитів. duplicateIndexes — порожньо (точних дублікатів нема).

⚠️ Великі документи (локальний docScan=full)

Ризик: ліміт документа Mongo — 16 MB. *_sender_lady_histories ростуть і вже близько:

Колекціяmax docдоків >1 MB>8 MB
prime_sender_lady_histories9.51 MB1574
chathouse_sender_lady_histories8.40 MB3451
udate_sender_lady_histories5.98 MB3840
udate_favorites5.57 MB180
udate_action_operators1.80 MB60
chathouse_action_operators1.32 MB10
udate_saveddataforladies1.16 MB30

*_sender_lady_histories — десятки/сотні KB–MB на документ (avg 0.5–2 MiB). *_action_operators — avg 60–140 KiB/doc. Схоже на доки з масивом, що росте без межі. TODO: перевірити структуру; 4 доки в prime вже >8MB — при 16MB запис впаде.

Найбільші колекції — за обсягом даних

Сортовано за data size (реальний обсяг, майже однаковий прод/локал — на відміну від storage, який на проді роздутий). Збігається з Compass, відсортованим за «Data size». avg/doc = dataSize / count.

Колекціяданіdocsavg/doc
prime_action_operators2.92 GB20.6K141.6 KB
golden_action_operators2.42 GB24.6K98.1 KB
udate_action_operators1.95 GB17.9K109.2 KB
chathouse_sender_lady_histories1.37 GB8751.56 MB
chathouse_action_operators1.15 GB18.8K61.2 KB
udate_sender_lady_histories933.41 MB1.3K733 KB
golden_online_users922.53 MB100K9.2 KB
golden_online_times911.90 MB3.8M240 B
log_ladies892.49 MB2.7M330 B
golden_statistics838.96 MB3.5M241 B
prime_favorite_actions743.15 MB4.5M165 B
prime_log_ladies671.54 MB1.6M414 B
golden_history_sending_mails650.48 MB6.8M95 B
chathouse_statistics639.07 MB2.4M270 B

За кількістю документів (прод)

Колекціяdocsдані
golden_history_sending_mails6.8M650.48 MB
prime_favorite_actions4.5M743.15 MB
golden_online_times3.8M911.90 MB
golden_statistics3.5M838.96 MB
log_ladies2.7M892.49 MB
prime_deepl_usings2.5M246.11 MB
chathouse_statistics2.4M639.07 MB
golden_history_sending_messages2.0M429.30 MB
udate_sendicebreakers1.7M290.11 MB
prime_log_ladies1.6M671.54 MB

Інші флаги

  • index-heavier-than-data (~52 колекції): індекси важчі за дані. Переважно дрібні службові (*_admins, *-supervisors, settings, user-*-families) + churn-колекції (prime_task_completed_or_canceleds, golden_history_sending_mails).
  • Порожні колекції (10): ai_notes, golden_man_notes, golden_send_history, chathouse_lady_event_logs, chathouse_not_enougth_ices_ladies, udate_hidden_mail_histories, udate_history_profit_ladies, udate_operator_actions, udate_statistics_request_queues, udate_temporary_statistics. TODO: перевірити чи дроп.
  • Підозра на сміття: teststoragetokenforusers_udates (206 MiB / 263 тис. доків, назва «test…»), test-user-operator2 (1 док, 4 індекси). TODO: підтвердити.

Підсумок: пріоритети чистки (перевірити)

  1. Compact / resync прода — поверне ~5 GB. Найбільші: academy_answers, prime_task_completed_or_canceleds, golden_history_sending_mails.
  2. Дроп невикористаних індексів (прод-список вище) — ~300 MB + швидший запис. Почати з golden_history_sending_messages (135.86 MB) і всіх вторинних у prime_task_completed_or_canceleds.
  3. Перевірити безмежний ріст *_sender_lady_histories — 16MB-ризик.
  4. Прибрати надлишкові префіксні індекси (звіривши плани запитів).

Дроп/compact — рішення людини, не з цього аналізу. Ендпоінт лише read-only діагностика.

Як оновлювати

  1. Прод (golden на проді): GET /golden/debug/db-analysis?docScan=off → невикористані індекси, фрагментація, живі розміри.
  2. Локально (golden на свіжому дампі): ?docScan=full → точні max doc size, структурний аналіз.
  3. Оновити дати/аптайм у шапці. Дельта prod.totalSize − dump.totalSize = поточний обсяг фрагментації.

TODO: додати ноду на architecture/Canvas.canvas (за конвенцією кожен файл = нода).