Map/Reduce своими руками — Apache CouchDb

    Логотип CouchDb Предупреждаю — мой взгляд совершенно не претендует на какую бы то ни было объективность. Но реляционные базы данных меня никогда, мягко говоря, не вдохновляли.

    Нет, я вполне понимаю когда у вас действительно приложение ориентировано на обработку и хранение больших массивов данных. Ну, ERP-системы, всякие хранилища, статистика там, «в прошлом месяце продали сто тыщ карандашей, в этом двести».

    С другой стороны, в большинстве случаев, когда речь идет о десктопных (или веб-) приложениях, где не нужно ворочать миллионами примитивных записей,  а приложение работает с относительно высокоуровневыми, сложными объектами, суть «дизайна и проектирования баз данных» заключается в повторении двух действий:


    а) расколупать эти высокоуровневые объекты на кучу простейших полей — чисел, строк и сложных зависимостей между ними, и раскидать  между десятками таблиц. Обычно это не очень сложно, однако некоторые (или многие?) типы данных не так уж приятно и органично раскладываются в этой модели — например, теги у записей в блоге;

    б) затем упорно собирать эти поля в объекты обратно, пользуясь четырехэтажными JOIN'ами, мегабайтами кода врапперов, кривыми и не очень слоями ORM — в зависимости от квалификации разработчика, в общем, всячески преодолевать пресловутый O/R impedance mismatch. При этом и рукописные JOIN'ы не показывают чудеса производительности и гибкости, а сгенеренные автоматически умным слоем врапперов — тем более.

    Схема базы данных CRM SalesLogix 7В принципе, ORM-библиотеки в динамических языках (см. SQLAlchemy) довольно приятны в обращении, однако и они не позволяют элегантно решить еще один болезненный вопрос — с апгрейдом схемы.

    В общем, немало приложений используют базы данных для хранения сложных структур данных, и при этом действительно сложные запросы с использованием внутренних зависимостей к этим данным им на практике нужны редко, или вообще не нужны (если не считать мега-JOIN'ов для того, чтобы просто обратно выковырять эти свои структуры из БД). Похоже, обычная RDBMS мало подходит для них — упомянутые выше проблемы довольно болезненно решаются, а миллионы человекочасов тратятся разработчиками БД на реализацию других, бесполезных для них возможностей.

    Одним решением являются объектно-ориентированные хранилища, они действительно становятся довольно популярны и заслуживают отдельного разговора. Они прозрачно решают проблему с ORM, но, если говорить о веб-приложениях (которые весьма интересуют нас в свете обещаной новой версии defun.ru :), объектно-ориентированные базы это таки не совсем то, что доктор прописал — они не решают проблем горизонтальной масштабируемости и распределенности данных, да и веб — это прежде всего много текстовой информации, неплохо было бы как-то учесть и это.

    Итак, CouchDb — документоориентированная база данных. Хранить она умеет документы — объекты, состоящие из кучи полей с произвольной структурой. У каждого документа есть только два обязательных служебных поля: имя и версия, имена уникальны и находятся в линейном пространстве — представьте себе гигантскую директорию с файлами-документами, вроде такого:

    { 
     "_id":"63086444D554D3094C080F96D5005B03",
     "_rev":"1837603925",
     "author":"lrrr",
     "tags":["baz","test","ru"],
     "url":"http:\/\/incubator.apache.org/couchdb",
     "title":"couchdb home",
     "description":"boo boo ba ba",
     "type":"story",
     "comments":1,
     "votes":2
    }


    Версии нужны для организации параллельного доступа к базе данных — вспомните как работает ваша система контроля версий — если мы хотим изменить документ, мы просто берем его, меняем и пытаемся положить обратно — если за это время его версия не поменялась, все отлично, если поменялась — можно просто попробовать внести те же изменения еще раз, с новым документом, или еще как-то сделать merge (в зависимости от приложения). Это называется optimistic locking, основной плюс — никто не блокирует документ на время редактирования, и поэтому не нужно ждать разблокировки. Кстати, такой механизм может применяться и в некоторых современных RDBMS, только на уровне строк в таблице (см. http://www.google.com/search?q=%22row+versioning%22).

    Архитектура CouchDb
    Интерфейс к CouchDb — исключительно HTTP, исключительно  REST, а ответ от сервера приходит в формате JSON. Поначалу это несколько настораживает — не самый эффективный протокол, но с учетом того что высокоуровневые документы хранятся в ней целиком, делать по 5-10 запросов к базе на каждый чих и не нужно. А плюсов куча: во-первых, любой язык умеет работать с HTTP и JSON (а если не умеет, легко научить), во-вторых — легко отлаживать, в третьих — CouchDb понимает HTTP Etag и If-None-Match, а значит можно без особых усилий прикрутить к базе HTTP кэш. 

    Зато масштабироваться вширь все должно отлично — в конце концов, примерно по такой схеме построены и Amazon SimpleDb, и Google BigTable. Удивительное, кстати совпадение, но и SimpleDb, и CouchDb написаны на эрланге ;)

    Что выгодно отличает CouchDb от сервисов гугла и амазона, так это более «продвинутая» функциональность в области запросов к данным.

    Естественно, что менее структурированные данные обрабатывать сложнее, и, раз уж мы так заботимся о масштабируемости — запросы эти тоже должны легко распределяться по кластеру серверов БД. Для этого CouchDb использует паттерн map/reduce, описаный в известной статье инженеров Google.
     
    map & reduce



    На практике выглядит это так: на сервере, в специальных документах хранятся view-функции (собственно map() и reduce()), преобразующие набор документов нужным образом, и к ним можно обращаться с помощью того же REST интерфейса. Вычисляться они умеют постепенно, с сохранением промежуточных результатов, то есть, если между двумя вызовами view добавился или изменился один два документа, то функция будет вызвана только для них. Пишутся они на JavaScript, но можно несложно подключить вместо этого python/ruby/что-то еще.

    В качестве дополнительного бонуса — поддержка полнотекстового поиска по документам, с помощью любой внешней библиотеки (пока авторы прикрутили к CouchDb поисковик Apache Lucene).

    * * *

    В конце обычно принято немного попинать рассматриваемую технологию, но CouchDb мне пинать пока жалко — слишком приятное впечатление производит. Хотя, конечно, это пока всего лишь альфа-версия, со всеми вытекающими последствиями (reduce, скажем, появился в транке три дня назад). Да, она очень небыстрая — пока умеет обрабатывать порядка десятков insert'ов в секунду (если не использовать режим bulk update) и да, она жрет очень много дискового пространства — так как все промежуточные версии документа сохраняются, если их периодически не удалить специальной функцией «Compact Database» — впрочем, это можно делать параллельно, не останавливая приложение. Однако для альфы система весьма стабильна и уже имеет, среди всего прочего, очень приятный и функциональный веб-интерфейс для администрирования и разработки.

    Оригинальный пост

    Еще ссылки:


    Поделиться публикацией

    Комментарии 61

      +1
      занимательный пост
        +5
        Отличнейшая статья, резко контрастирует с большинством других заметок, публикуемых на хабре. Поставил бы большущий плюсище, если б мог.
          0
          Согласен, поэтому поставил плюс и посту, и карме, и Вашему каменту. Как раз вчера слышал про этот проект, буду ждать его развития.
          0
          держите в курсе, интересно как будет развиваться :)
          спасибо за пост (плюс поставил)
            0
            ну, еще один success story для Erlang'а

            кстати, интересно почитать "Why Does CouchDB Not Use Mnesia?" в их FAQ(mnesia — это встроенная в Erlang распределенная БД)
              0
              Ну success story пока можно назвать только амазоновский сервис :)

              А mnesia (или даже тупо ets) отлично дополняет CouchDb — она ж довольно шустрая, там можно хранить разнообразные кэши и сессии юзеров.
              +6
              встречаем отечественную разработку — StrokeDB

              вот что там пишут о CouchDB, кстати:


              CouchDB is very nice, but has several disadvantages for us. We plan to port a kernel of the StrokeDB to “thin client” languages (JavaScript, ActionScript etc.) to enable offline work with the data with the very same features server version has. CouchDB is written in Erlang and that’s the first problem.
              Another thing is that CouchDB doesn’t scale data properly yet. It lacks distributed indexes and storages.
              There’s also a huge argument for pure-Ruby version: StrokeDB integrates so well with Ruby apps, so it is a pleasure to configure different environments and optimize performance by injecting the database right into your application.
                0
                это от создателя "вкадре.ру"? :)
                  0
                  угумс
                    0
                    Он, кстати, есть на Хабре - жестко заминусованный :) посмотреть профиль oleganza
                      0
                      нормально, у меня такая же карма была :) но спасибо, было интересно увидеть его тут.
                  0
                  Хоть что-то интересное , а то либо "как меньше спать и больше работать" либо "я голодный студент дайте мне работу" .
                    0
                    Relational Databases are dead, long live relational databases.
                      0
                      Таких постов становится много (например как минимум два есть на инсайт-айти). Их общий недостаток - автор помимо теории, как правило, понятия не имеет о практической реализации проектов с использованием подобных БД.

                      Было бы неплохо добавлять какой-то мини тестовый проект который бы показал разработчикам (и потенциальным пользователям таких БД) насколько удобна система в конфигурации, насколько много времени занимает ее развертывание и т.д.

                      А так получается еще одна перепечатка абаута с апача.
                        0
                        Развертывание занимает пять минут — svn co && ./bootstrap && ./configure && make && make install, никаких проблем.

                        Насколько удобна в конфигурации — проще самому посмотреть. Тут, кстати, в ближайшей версии ожидаются существенные изменения.

                        Насчет практики — будет отдельный отчет, когда запустим defun.ru на эрланге и couchdb :) Работа идет.
                          0
                          Простите, но у вас же там Друпал. Или вы свой движок написали?
                            0
                            Да, друпал, но это временно. Пишем свой.

                            Новая версия будет совсем новая, в смысле — в ней не будет ни строчки от старой: ни друпала, ни пхп, ни mysql, ни даже апача :)
                              0
                              Ну что сказать. Поздравляю :)
                        0
                        Чем-то мне это напомнило ZODB - базу данных от Zope. Много красивых идей, каждый объект содержит все поля, джойны не нужны и т.п.
                        Но работает эта штука... примерно как называется, так и работает :)
                          0
                          Она работает хорошо, по скорости выборки (поднятие объекта по ИД) обгонит многие селекты. Однако конкурентная запись там порождала постоянные ZODB Conflict Errorы.
                          С тех пор я буду долго изучать объектную (или подобную) базу данных, прежде чем начну использовать, особенно при нагрузке.
                          Однако скорость разработки на Zope была более чем заманчивой (:
                            0
                            Насчет скорости очень спорно. Вот товарищ чуть ниже как раз опровергает это мнение. Скорость выборки примерно равна, а запись отстает на 2 порядка(!). Кроме того, после большого числа записей базу раздувает неимоверно, необходимо делать упаковку.
                            Какие именно выборки имеются ввиду? Как быстро будет выбираться не просто объект, а скажем группа последний новостей по данному тегу, к которому есть право доступа у пользователя?
                              0
                              Вобщем у меня примерно такие же впечатления. На первый взгляд все круто. А когда копнешь глубже, то вылезает масса проблем.
                              0
                              Почитай статью про сравнение производительности ZODB и MySQL http://zope3.ru/stati/testiruem-zodb-na-… Работает она прекрасно, вот только не всегда результаты от неправильно поставленных задач соответствуют ожиданиям
                                0
                                Прочитал. Ты только подтвердил мой тезис. Проигрыш по скорости записи на 2 порядка плюс проблемы с конкурентностью, а по скорости выборки примерно одинаково. На самой простой операции выборки zodb оказалась быстрее в 2 раза. При этом не забываем, что zodb хранит свой индекс в памяти. С одной стороны это дает ей выигрыш по скорости, а с другой привносит ограничения на размер, которых нет у того же мускуля. А если взять операцию поинтереснее? Типа 20 последних новостей по выбранному тегу с учетом прав доступа?
                                В простом случае можно использовать zcatalog, а в более сложных начинаются веселые фокусы - ...индекс выносится в реляционную БД :) Ха! Так зачем городить весь огород, если все равно пришли к тому же? Только сделали жуткогетерогенную систему, которая уже сама в себе таит проблемы.
                              +1
                              Не реляционный язык программирования для баз данных mumps/m, рулил когда современные SQL были еще в зародыше, но в 90е одна компания с ужасным маркетингом и подходом ведения бизнеса, почти как у Майкрософт (только еще хуже) скупила все коммерческие реализации (с десяток компаний), и заморозила соответствующие продукты, фактически они монополизировали этот рынок.
                              Речь о компании Intersystems.
                              Тупо надстроив SQL транслятор над M технологией они назвали это Каше(Cach
                                0
                                Ха-ха, хабр подавился буковкой из названия программного продукта.
                                0
                                отличная статься... большое спасибо
                                  0
                                  слэч ты правда думаешь, что ЭТО будет работать с нормальным количеством записей? Максимум помоему на что ЭТО способно - хранение конфигов :)
                                    0
                                    =)) а ты не мысли записями, ты мысли ДОКУМЕНТАМИ и ОБЪЕКТАМИ
                                    и тогда все встанет на свои места

                                    я думаю что это будет нормально работать на коллекции до 100 000 документов на один шард

                                    основной прикол в ДРУГОМ подходе
                                    нахер джойны и нормальные формы, даешь денормализацию и произвольную иерархию внутри объекта с безболезненным изменением схемы =)
                                  +1
                                  боюсь все же в web приложениях объекты наоборот проще, чем ERP приложениях.
                                    0
                                    C ERP я там погорячился, да, не так все просто.
                                    0
                                    простите, я правильно понимаю, что для того чтобы найти все документы по какому то критерию, и потом
                                    надо писать map функцию???
                                    а для того чтобы потом из найденных документов вытащить какие то конкретные поля и на их основе составить какой нибудь "сгрупированный" и "отсортированный" результат, надо писать reduce ф-цию???
                                      +1
                                      Половина первого предложения куда-то пропала у вас, но ответ скорее всего "да" на оба вопроса :)

                                      Да, эти механизмы предполагаются довольно-таки легкими и шустрыми, и эту часть логики предлагается перенести на сторону БД. Результаты работы map/reduce тоже можно фильтровать — на выходе у них не просто документы или часть документов, а пары json-объектов {ключ, значение}, и через HTTP API можно запрашивать не все результаты, а только для диапазона ключей, или первые N, и т.п.

                                      Вот хороший пример, как примерно это выглядит на практике.
                                      0
                                      Больше всего хотел бы увидеть пример реализации стандартного веб-приложения с использованием этой (или любой другой среди всех этих нереляционных) базы. Приложение самое простое, есть база (таблица) статей на сайте, БД пользователей они регистрируются на сайте, они могут оставлять комментарии к этим статьям, и все это выглядит ну к примеру как элементарных новостной сайт или блог.
                                        0
                                        Любой сайт на Lotus Notes/Domino.
                                        Вообще, Notes, по-моему, старейшая из документоориентированных СУБД.
                                          +2
                                          Да, кстати, Damien Katz был каким-то мощным консультантом по Notes, соавтором книжки какой-то по ним и все такое. Потом в IBM лет пять работал непосредственно над Lotus Notes, потом ушел, написал CouchDb, и теперь с января его IBM обратно наняла чтоб он над CouchDb уже фултайм работал.

                                          Вот такая вот загогулина :)
                                            0
                                            Надо же, оказывается я читал его историю о том как он переписывал движок @-формул, для шестого Лотуса.
                                            То-то я смотрю, похоже на Notes — документы, поля...
                                            0
                                            странно. для домино у IBM есть почти рабочий мост .nsf -> DB2, который позволяет фактически запихивать неструктурированные данные в реляционную базу.
                                            Добавление еще одной сущности (CouchDb)? как-то нелогично. если CouchDB они поверх DB2 гонять - получится урезанный Domino, только без собак и LotusScript (а яву наверняка прикрутят, имхо)
                                              0
                                              Насколько я понимаю, у IBM пока нету планов куда-то прикручивать CouchDb. Это совершенно отдельный проект, появился он независимо от них, они его просто "под крыло" взяли — они же вообще много open source проектов спонсируют.
                                        0
                                        Все это конечно хорошо, интересно посмотреть на "select". Каким способом будет производиться поиск, и как скажется большие объемы данных на этот поиск?
                                          0
                                          В теории для данного подхода большие объемы будут не так пагубны как для реляционной базы. Когда нужно обрабатывать десятки и сотни терабайт данных то тут выигрыш будет налицо. Но как будет именно в данном случае (не забываем что альфа версия) это еще неизвестно.
                                            0
                                            Как раз таки в теории именно для такого подхода хранения данных поиск скажется не лучшим образом.
                                            Можете точнее прокомментировать в чем и как"выигрыш будет налицо"?
                                              +1
                                              Смотря какие select'ы имеются ввиду.

                                              Тут результат выборки строится инкрементально — то есть промежуточные результаты сохраняются и повторно используются при последующих запросах. Я не разработчик RDBMS, конечно, но, мне кажется, вряд ли они могут делать так же — слишком много разных запросов может быть (а в couchdb их набор фактически заранее задан разработчиком). Функции map/reduce распраллеливаются на кластере на ура.

                                              А основная засада с джоинами: с обычными RDBMS приходится либо их использовать — а они масштабируются со скрипом и работают небыстро, либо использовать суровую денормализацию, в результате мощная СУБД используется в режиме гигантской тупой хэш-таблицы, причем куча усилий разработчиков тратится на сборку/разборку результатов запросов в объекты предметной области, кэширование, partitioning и борьбу со схемами (при этом, в денормализованных таблицах они уже не могут поддерживать consistency).
                                                0
                                                select'ы имелись ввиду " where name='вася'" или "between дата1 and дата2". Не могу себе представить быстрого поиска без создания ключа. По сути джоины это и есть поиск + добавление.
                                              0
                                              Почему поиск скажется не лучшим образом? Ну как минимум объем дисковых операций уменьшается. Ну и возможность раскидывания по кластеру нужного размера почти без потери производительности разве не полезна при большом объеме данных? Имхо как раз это то самое в чем проблема реляционных баз для больших объемов. Опять же это для документов, они вряд ли короткие, а реляционные БД лучше заточены под таблицы с малым размером столбцов и короткой длине их содержимого.
                                              Да и википедия говорит что для data warehouses лучше колоночная БД
                                              Ну а для примера можете посмотреть на гугль, у него отнюдь не маленькая база, я бы сказал что она вполне себе подходит под критерии больших объемов данных. Так вот их BigTable вполне тянет все это.
                                              Я не эксперт по БД, не сертифицировался, так что могу и ошибаться. В таком случае буду рад услышать преимущества реляционной структуры, перед всеми этими колоночными БД, для случая хранения большой базы текстовых документов.
                                                0
                                                > Ну как минимум объем дисковых операций уменьшается.
                                                Это почему? С чего вы взяли? Как раз таки поиску без ключа придется просмотреть все записи, которые лежат на винтах!

                                                > Ну и возможность раскидывания по кластеру нужного ...
                                                Кластеризация это обычная вещь для "нормальной" СУБД. И это не проблема.

                                                Мне интересно на низком уровне как будет осуществляться поиск в неструктурируемых данных по какому нибудь полю. Нет ключа, что означает что данные не отсортированы. Я не смогу принять решение не просмотрев всех записей (допустим min(дата)).
                                                  0
                                                  Нет-нет, смотрите: само хранилище — это тупо набор документов, неструктурированных. Точнее, индексированных только по имени.

                                                  Плюс к документам есть набор view, то бишь срезов, отображающих с помощью функций map/reduce множество документов в список {key, value}, отсортированный, естественно, по ключу. То есть view это индекс такой по сути (ключ тут, кстати, довольно сложный может быть, не просто циферка или строчка).

                                                  При этом и построение этих срезов, и выборка из них легко масштабируются и распределяются по кластеру.
                                                    0
                                                    Ну теперь более менее понятно, спасибо за разъяснения. А нет ли у вас тестов скорости?
                                                      0
                                                      По скорости вставки она довольно небыстрая, вот тут есть какие-то результаты, http://userprimary.net/user/2007/12/16/a…, и я сам похожие цифры наблюдал.

                                                      Насчет чтения не знаю, должно быть довольно шустро, но все сильно зависит от размера выборки, как давно не пересчитывался view и так далее. Тут чтоб нормально потестировать нужен стенд тестовый, вообще говоря.
                                                        0
                                                        Не очень впечатляет. Но все равно буду посматривать за развитием этого проекта.
                                          0
                                          Аналог Лотуса, я так понимаю... Изучал Лотус в IBM - они утверждают, что всё равно бэкенд частично реляционный, так как у документоориентированной БД очень большие проблемы с производительностью.
                                            0
                                            Спасибо за информацию, будем пробовать :) Вам плюс.
                                              0
                                              Очень занимательно. Отплюсовал.
                                              А отчего вы про Erlang как-то перестали писать?
                                                0
                                                Ну, это тоже про эрланг отчасти :)

                                                Просто сейчас почти все свободное время уходит на то чтоб *на* эрланге писать. Новые впечатления пока коплю, в общем :)
                                                0
                                                как на счет реализованных web проектов на couchDB - они есть , если да то насколько крупные ?
                                                  0
                                                  Поскольку это пока альфа, API меняется, фичи актвно добавляются — крупных проектов, понятно, нету. Сейчас нужно быть таким тру early adopter'ом чтоб ее промышленно использовать, хотя в этом тоже есть свои плюсы — пока проект не разросся, его проще подпилить напильником в нужных местах самому.

                                                  Тут вот список проектов, он небольшой
                                                  http://wiki.apache.org/couchdb/InTheWild
                                                  0
                                                  Звучит жизнеутверждающе. Пошел копаться :)
                                                    0
                                                    Извиняюсь за некропостинг. Прошло два с половиной года. Что вы скажете сейчас о CouchDB? Есть практика использования?

                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                    Самое читаемое