Не используйте MongoDB

Раз за разом встречаю case, в котором разработчики сначала выбрали MongoDB, а спустя 3..5 лет привычно слизывают иголки кактуса. При этом после стольких лет эксплуатации миграция в другую БД будет ещё большим кактусом, потому… так и живут, в общем.
Так вот, если выбор MongoDB вам кажется хорошей идеей (в контексте большого, живущего долго и обильно сервиса), подумайте ещё раз. И ещё. И ещё раз пять, обсудив желание с теми, кто уже получил достаточно долгий опыт. Убедитесь, что вы и в самом деле понимаете, во что вляпываетесь. Только тогда используйте.
А если вы привыкли к инструментам и возможностям большой тройки RDBMS (Oracle, PostgreSQL, MySQL), откажитесь от «хорошей идеи» сразу, минуя стадию размышлений и обсуждений.

Сначала о хорошем.
MongoDB отлично подходит для хранения и извлечения древовидных структур данных. Иначе говоря, ровно для того, от чего первоначально поднялся hype — откуда-то прилетает развесистый JSON, а вы его целиком после минимальной конвертации фигак-с в базу, затем целиком фигак-с из базы. Пишется довольно быстро, забирается ещё быстрее. Уря-уря.
А вот дальше всё не так хорошо. Накидаю разбросом.

Умеете ли вы и ваши разработчики жить в условиях анархии? Это когда ограничений нет не только у гениальности и сознательности, но также у глупости, невежества и пофигизма. У MongoDB нет схемы на уровне базы данных. В терминах RDBMS… скажем, у вас таблицы без FK, триггеров, без типов данных. Зато есть разработчики, которые хотят на ручки и смузи, чтобы было меньше работы. Скучной, нудной, требующей кропотливости и тщательности. Ну не любят нежные зайки таблицы проектировать и по крупицам что-нибудь проверять. А тут такая щедрая MongoDB.
Прошло 3 года. У вас 50GB data size, 50 collections и 100M objects. Вася уволился в первый год. Петя ушёл в запой на второй год. Игнат в третий год устроил рефакторинг (лучше б пельмени лепил). Вопреки всем рекомендациям и увещеваниям у коллекций есть «виртуальные» связи между собою (те же foreign keys, но без них). Угадайте, насколько целостными являются данные? Угадайте, какие варианты значений могут быть у какого-нибудь поля (попутно угадайте, всегда ли это поле вообще есть)? Именно угадайте. А если вам не нравится угадывать количество дыма без огня в production, вы озадачитесь мегатонной кода, который обойдёт каждый документ, заглянет в каждое поле и сверит хотя бы варианты «у нас нет яблока в ведре гвоздей». Прогноз результата зависит от того, насколько вы доверчивы и наивны. Разработчики обязательно всё делали хорошо, правильно и не в режиме «быстро-быстро говнякаем, нам надо срочно в прод». Конечно. Как иначе-то.

Любите ли вы транзакции? Нет? MongoDB тоже не любит. Безусловно, можно подкрасить глаза кровью и на основе Atomicity and Transactions соорудить что-нибудь похожее, но к нормальным транзакциям вы только приблизитесь.
Чревато это весьма занятными эффектами, когда в процессе записи чего-нибудь в две разные коллекции ваше приложение ляжет. Или MongoDB ляжет. Или сеть пропадёт. В общем, произойдёт событие, которое прервёт запись десяти примет преступника в розыске на второй примете. Есть люди, которых это не волнует. Как привык уже думать, у каждого своя трактовка качества продукта. Зато те, кто озадачится темой «чё дальше делать», обнаружат, что механизмов rollback’а нет. И либо те же разработчики (вспомним, эти ребята не хотели тратить время на рутину) будут костылить в приложении откаты и докаты данных с попутной проверкой целостности, либо живите на мине с часиками. Однажды стопудово рванёт.

Выразительность языка запросов в MongoDB несколько хромает. Как и эстетика. Верю, что кому-нибудь может нравиться {size: {$ne: 0}} вместо size <> 0, но общего с такими людьми иметь не хочется.
Ладно, эстетика. Самый сладкий צימעס в том, как удобно работать с большими запросами. У вас адовый JSON на экран. Месиво из фигурных скобок, долларов и двоеточий. Удобно грепать. Удобно парсить глазами. Удобно писать меленькие конструкторы для запросов (как всё ещё пишут иногда для SQL). Шучу. Удобство нулевое.
Что любопытно, несколько лет назад в сети был движняк, показывающий примеры, как няшно выглядят запросы MongoDB в сравнении с SQL. Мол, вот тут одна строчка вместо этого ужас-ужас, пользуйтесь нашим сахарком. И да, в тех примерах вроде бы всё верно. Вот только существует масса примеров с обратной стороны, когда привычный и семантически эквивалентный SQL-запрос превращается в неудобоваримый ужас-ужас.

Недавно один товарищ не смог ответить на простой вопрос: что такое [де]нормализованные данные? Так вот разницу между этими состояниями легко можно познать в процессе миграции из одного в другое. Нормализованные (если поняли, что несколько ошиблись в выбором RDBMS и надо другое) катнуть в какую-нибудь NoSQL достаточно просто. А вот из MongoDB в SomethingSQL… ха-ха, в цирке смешно уже не будет никогда. Нет, правда. Меня всякий раз так радуют восхищённые ребята, лишившие себя нужды вносить строгость в виде схем данных, проверок и прочего. Счастья им и здоровья, ждёт море открытий чудных.

Оно жрёт память. Как не в себя. Что RAM, что HDD/SSD. И если на винт ещё как-то ладно бы (всё равно бывает грустно, впрочем), то куда ж ты, зараза такая, перевариваешь оперативку? Начинаешь гуглить. Начинаешь читать совсем уж дебри мануалов. И обнаруживается, что даже WiredTiger всё, везде и всегда кладёт в RAM. Ну а чё? Кто в школу для взрослых ходил, знает, что это прям вот почти самая быстрая доступная память (не в регистры процессора же класть), давайте использовать её. Использует. Так, что у OOM killer порою глаз дёргается. Я, конечно, могу у WT ограничить cacheSizeGB, но станет ли MongoDB хорошо? Обжора, которому желудок ушили, вряд ли радостен.
На дисках, всё-таки к слову, тоже могло быть шоколаднее. Живёт базка. Кушает винт. Кушает, кушает. Решаете вы в коллекции на 500M документов грохнуть половину. Грохаете. Уря? Неть. MongoDB не отпустит место на винте. Чтобы отпустила, надо выполнить compact, который блокирует всё, до чего дотянется. Запланируйте даунтайм всего, это же так интересно.

Отдельное удовольствие причиняет поиск и устранение причин, по которым запрос работает медленно. Тут не могу удержаться и не упомянуть прекрасный принцип, по которому WiredTiger решает, как всё-таки выполнять запрос (индексы и т.д.) — он его сначала выполняет.
Так вот. Даже если предположить, что вы научились правильно читать результат explain, дальше-то что? Если в RDBMS особенно упорные бойцы вспомнят реляционную алгебру, достанут пыльный том Дейта и пятистраничный запрос зажмут в тиски оптимизации, то MongoDB-бойцы как выкрутятся? Обычно выкручиваются прям вот бодро. Сначала создают дополнительные индексы. Ну вдруг поможет. Не помогает. Потом разбивают запрос на несколько запросов (один фиг привычно по временам, когда в MongoDB ничего близко рядом с JOIN не было). Не помогает. Потом дробят свои милые толстеееенные документы с десятками уровнями вложенности на менее вложенные. Чуть-чуть помогает, но подозрительно напоминает схему RDBMS. Потом топятся в ближайшем пруду.
Ибо запихнуть вековые деревья в базу ума большого не надо. А вот обеспечить быстрый поиск с какой-нибудь агрегацией по этим деревьям — оно порою до кандидатских доходит. Но вы же хотели не кандидатскую, а пыщ-пыщ и ололо, да?

В финале не могу пройти мимо механизма локов. Очень советую почитать FAQ: Concurrency, очень. Обратите внимание на ситуации, в которых лочится вся база. Прочтите страницу ещё раз. Потом обратите внимание на то, как лочатся документы (они ведь у вас толстенькие и вы частенько внутри документа добавляете / удаляете, да?). Ещё раз перечитайте. И ещё. До полного просветления. Даже пересказывать не буду, это надо пробовать лично.

Существуют проекты, у которых получилось приготовить MongoDB правильно, при этом в базе прям вот хотя бы middle data, над которой middle load. Там диктатура, сплошь настоящие senior’ы и всё по заветам. Такие проекты рапортуют об успехах, хоть сейчас разводись и женись на MongoDB. Но чёт вот наблюдение за действительностью (от личного опыта до яростных репортов в рассылках) показывает, что в общем случае MongoDB сначала надо учиться готовить. Учиться истово, системно, долго. С умным анализом, с прогнозами в горизонт до пяти лет. Тут можно закрыть глаза и пофантазировать о том, как разработчики читают учебники с мануалами, грызут курсы MDBU, да ещё и сертификацию сдают… Ага.
Уф. Ну вроде по верхам вот так. Удачи отважным.

Не используйте MongoDB: Один комментарий

Добавить комментарий