Вынесено из комментов к посту
vitus_wagner’а про pump.io.
Из опыта работы с MongoDB получается, что её писали вредители. Абсолютно весь API и дизайн заточен под то, чтобы как можно сильнее оградить клиентский код от возможности делать полезные запросы к базе и увеличить вероятность непреднамеренного уничтожения данных.
Типичный симптом при использовании Mongo — приложение работает, пока объём или количество документов в базе не превышает некоторого эпсилона, достаточно большого, чтобы проблемы не возникали в тестировании.
Во-первых, Mongo — блокировочник. То есть, когда в базу идёт активная запись, все читатели сидят и ждут, пока писатель соизволит отпустить блокировку.
Во-вторых, Mongo очень неохотно освобождает дисковое пространство. То есть логически удаляемые записи физически продолжают занимать место, до ближайшей компактизации. Компактизация требует, чтобы на файловой системе было свободно хотя бы ещё столько же места, сколько база уже занимает. То есть, компактизация базы, уже сожравшей всё свободное место, штатными средствами невозможна — туши сервер, снимай бэкап по сети, дропай файлы базы, перезаливай с бэкапа.
Иногда делу можно помочь ограниченными (capped) коллекциями. Это такая коллекция, которая растёт только до определённого предела. Ограничение устанавливается на общий размер данных в коллекции. Не на количество документов, не на возраст самого старого документа — на размер. Чисто техническая реализация, без какой-либо оглядки на предметную область. Далее, реализованы они так, что документы можно модифицировать, но только в сторону уменьшения размера. Удалять документы из capped коллекций нельзя, только дождаться, пока они будут удалены автоматически (при вставке очередного документа). Или можно очистить всю коллекцию. Короче говоря, capped коллекции очень ограничены в функциональности по сравнению с обычными.
В-третьих, документы Mongo ограничены в объёме неким искусственным лимитом в 16 мегабайт. Это бы было ничего для конечных документов, хранимых в базе.
Однако, иногда с базы хочется посчитать какую-нибудь развесистую агрегацию — то, что в SQL делается однострочником вида group by или right join. Для этого есть встроенные агрегирующие функции. Которые как бы работают, но их результат является документом. Со всеми вытекающими последствиями, см. п. 3.
Поэтому для всех интересных агрегаций приходится использовать механизм map/reduce. Для того, чтобы начать мочь переформулировать запросы вида group by и right join, нужно вывернуть мозг в чисто-функциональную парадигму. Писать в базу из map/reduce нельзя, там разрешены только чистые функции. Нет, есть одна лазейка: функциям, используемым в map/reduce, разрешается использовать объект контекста (так называемый scope). Объект scope является документом. Все промежуточные результаты map и reduce являются документами. См. п. 3. Если потребовать результат map/reduce напрямую (как возвращаемое значение), то он тоже должен укладываться в лимит.
Но можно делать map/reduce в коллекцию, в этом случае ограничение на весь результат снимается. Ограничения на все промежуточные документы остаются.
Часть ограничений на промежуточные результаты удаётся обойти, если делать map/reduce не по всем данным, а частями, или регулярно с переиспользованием уже насчитанных данных. Это называется инкрементальным map/reduce’ом. По умолчанию инкрементальный map/reduce перетирает прошлые насчитанные данные новыми, а не объединяет. (Это к заявлению о непреднамеренной потере данных.)
В-четвёртых, запросы на обновление (модификацию) документов. У них есть один аргумент — критерий поиска, и другой — как модифицируем. И третий — флаги/опции. По умолчанию, Mongo найдёт один документ, удовлетворяющий критерию, заранее неизвестно какой. Это gotcha, намеренное[citation needed] отличие от семантики SQL. Чтобы модифицировать все соответствующие документы, нужно явно указать флаг. Далее, если параметр, указывающий изменения, не содержит специальных операторов, то целевой (обновляемый) документ просто будет перезаписан этим. (В отличие от SQL, где указанные в запросе поля будут обновлены, а остальные — оставлены без изменения.) Это всё тоже очень помогает непреднамеренно привести базу в неизвестное состояние, из которого в общем случае нельзя ни вернуться в исходное, ни получить желаемое. Транзакции с возможностью rollback’а? Не, не слышал.
В-пятых, Mongo нестойка к аварийному выключению. При внезапном прекращении процесса файлы базы могут остаться в неконсистентном состоянии, в котором сервис отказывается запускаться и требует ручного вмешательства. Совсем как MySQL/MyISAM. Нет, транзакционная/журналируемая файловая система не поможет.
И в-шестых, Mongo очень быстро принимает записываемые в неё документы (и этот факт способствует тому, чтобы её выбирали в качестве хранилища в новых проектах), но очень неохотно отдаёт их обратно. Бэкап данных из Mongo или полная выборка для целей обработки внешними средствами подчиняется всем законам блокировочников.
no subject
Date: 2014-06-15 16:38 (UTC)no subject
Date: 2014-06-15 18:36 (UTC)no subject
Date: 2014-06-16 01:13 (UTC)