Мультимодельные СУБД — основа современных информационных систем?

    Современные информационные системы достаточно сложны. Не в последнюю очередь их сложность обусловлена сложностью обрабатываемых в них данных. Сложность же данных зачастую заключается в многообразии используемых моделей данных. Так, например, когда данные становятся «большими», одной из доставляющих неудобства характеристик считается не только их объем («volume»), но и их разнообразие («variety»).


    Если вы пока не находите изъяна в рассуждениях, то читайте дальше.


    Шампунь 5-в-1



    Polyglot persistence


    Сказанное выше приводит к тому, что порою в рамках даже одной системы приходится для хранения данных и решения различных задач по их обработке использовать несколько различных СУБД, каждая из которых поддерживает свою модель данных. С легкой руки М. Фаулера, автора ряда известных книг и одного из соавторов Agile Manifesto, такая ситуация получила название многовариантного хранения («polyglot persistence»).


    Фаулеру принадлежит и следующий пример организации хранения данных в полнофункциональном и высоконагруженном приложении в сфере электронной коммерции.



    Пример этот, конечно, несколько утрированный, но некоторые соображения в пользу выбора той или иной СУБД для соответствующей цели можно найти, например, здесь.


    Понятно, что быть служителем в таком зоопарке нелегко.


    • Объем кода, выполняющего сохранение данных, растет пропорционально числу используемых СУБД; объем кода, синхронизирующего данные, — хорошо если не пропорционально квадрату этого числа.
    • Кратно числу используемых СУБД возрастают затраты на обеспечение enterprise-характеристик (масштабируемости, отказоустойчивости, высокой доступности) каждой из используемых СУБД.
    • Невозможно обеспечить enterprise-характеристики подсистемы хранения в целом — особенно транзакционность.

    С точки зрения директора зоопарка все выглядит так:


    • Кратное увеличение стоимости лицензий и техподдержки от производителя СУБД.
    • Раздутие штата и увеличение сроков.
    • Прямые финансовые потери или штрафные санкции из-за несогласованности данных.

    Имеет место значительный рост совокупной стоимости владения системой (TCO). Есть ли из ситуации «многовариантного хранения» какой-то выход?


    Мультимодельность


    Термин «многовариантное хранение» вошел в обиход в 2011 году. Осознание проблем подхода и поиск решения заняли несколько лет, и к 2015 году устами аналитиков Gartner ответ был сформулирован:


    • Из «Market Guide for NoSQL DBMSs — 2015»:
      Будущее СУБД, их архитектур и способов использования — мультимодельность.
    • Из «Magic Quadrant for ODBMS — 2016»:
      Ведущие операционные СУБД будут предлагать несколько моделей — реляционную и нереляционные — в составе единой платформы.

    Похоже, что в этот раз аналитики Gartner с прогнозом не ошиблись. Если зайти на страницу с основным рейтингом СУБД на DB-Engines, можно увидеть, что большая часть его лидеров позиционирует себя именно как мультимодельные СУБД. То же можно увидеть и на странице с любым частным рейтингом.


    В таблице ниже приведены СУБД — лидеры в каждом из частных рейтингов, заявляющие о своей мультимодельности. Для каждой СУБД указаны первоначальная поддерживаемая модель (когда-то бывшая единственной) и наряду с ней модели, поддерживаемые сейчас. Также приведены СУБД, позиционирующие себя как «изначально мультимодельные», не имеющие по заявлениям создателей какой-либо первоначальной унаследованной модели.


    СУБД Изначальная модель Дополнительные модели
    Oracle Реляционная Графовая, документная
    MS SQL Реляционная Графовая, документная
    PostgreSQL Реляционная Графовая*, документная
    MarkLogic Документная Графовая, реляционная
    MongoDB Документная Ключ-значение, графовая*
    DataStax Wide-column Документная, графовая
    Redis Ключ-значение Документная, графовая*
    ArangoDB Графовая, документная
    OrientDB Графовая, документная
    Azure CosmosDB Графовая, документная, реляционная

    Примечания к таблице

    Звездочками в таблице помечены утверждения, требующие оговорок:


    • СУБД PostgreSQL не поддерживает графовую модель данных, однако ее поддерживает такой продукт на ее основе, как, например, AgensGraph.
    • Применительно к MongoDB правильнее говорить скорее о наличии графовых операторов в языке запросов ($lookup, $graphLookup), чем о поддержке графовой модели, хотя, конечно, их введение потребовало некоторых оптимизаций на уровне физического хранения в направлении поддержки графовой модели.
    • Применительно к Redis имеется в виду расширение RedisGraph.

    Далее для каждого из классов мы покажем, как реализуется поддержка нескольких моделей в СУБД из этого класса. Наиболее важными будем считать реляционную, документную и графовую модели и на примерах конкретных СУБД показывать, как реализуются «недостающие».


    Мультимодельные СУБД на основе реляционной модели


    Ведущими СУБД в настоящее время являются реляционные, прогноз Gartner нельзя было бы считать сбывшимся, если бы РСУБД не демонстрировали движения в направлении мультимодельности. И они демонстрируют. Теперь соображения о том, что мультимодельная СУБД подобна швейцарскому ножу, которым ничего нельзя сделать хорошо, можно направлять сразу Ларри Эллисону.


    Автору, однако, больше нравится реализация мультимодельности в Microsoft SQL Server, на примере которого поддержка РСУБД документной и графовой моделей и будет описана.


    Документная модель в MS SQL Server


    О том, как в MS SQL Server реализована поддержка документной модели, на Хабре уже было две отличных статьи, ограничусь кратким пересказом и комментарием:



    Способ поддержки документной модели в MS SQL Server достаточно типичен для реляционных СУБД: JSON-документы предлагается хранить в обычных текстовых полях. Поддержка документной модели заключается в предоставлении специальных операторов для разбора этого JSON:


    • JSON_VALUE для извлечения скалярных значений атрибутов,
    • JSON_QUERY для извлечения поддокументов.

    Вторым аргументом обоих операторов является выражение в JSONPath-подобном синтаксисе.


    Абстрактно можно сказать, что хранимые таким образом документы не являются в реляционной СУБД «сущностями первого класса», в отличие от кортежей. Конкретно в MS SQL Server в настоящее время отсутствуют индексы по полям JSON-документов, что делает затруднительными операции соединения таблиц по значениям этих полей и даже выборку документов по этим значениям. Впрочем, возможно создать по такому полю вычислимый столбец и индекс по нему.


    Дополнительно MS SQL Server предоставляет возможность удобно конструировать JSON-документ из содержимого таблиц с помощью оператора FOR JSON PATH — возможность, в известном смысле противоположную предыдущей, обычному хранению. Понятно, что какой бы быстрой ни была РСУБД, такой подход противоречит идеологии документных СУБД, по сути хранящих готовые ответы на популярные запросы, и может решать лишь проблемы удобства разработки, но не быстродействия.


    Наконец, MS SQL Server позволяет решать задачу, обратную конструированию документа: можно разложить JSON по таблицам с помощью OPENJSON. Если документ не совсем плоский, потребуется использовать CROSS APPLY.


    Графовая модель в MS SQL Server


    Поддержка графовой (LPG) модели реализована в Microsoft SQL Server тоже вполне предсказуемо: предлагается использовать специальные таблицы для хранения узлов и для хранения ребер графа. Такие таблицы создаются с использованием выражений CREATE TABLE AS NODE и CREATE TABLE AS EDGE соответственно.


    Таблицы первого вида сходны с обычными таблицами для хранения записей с тем лишь внешним отличием, что в таблице присутствует системное поле $node_id — уникальный в пределах базы данных идентификатор узла графа.


    Аналогично, таблицы второго вида имеют системные поля $from_id и $to_id, записи в таких таблицах понятным образом задают связи между узлами. Для хранения связей каждого вида используется отдельная таблица.


    Проиллюстрируем сказанное примером. Пусть графовые данные имеют схему как на приведенном рисунке. Тогда для создания соответствующей структуры в базе данных нужно выполнить следующие DDL-запросы:


    CREATE TABLE Person (
      ID INTEGER NOT NULL,
      name VARCHAR(100)
    ) AS NODE;
    
    CREATE TABLE Cafe (
      ID INTEGER NOT NULL, 
      name VARCHAR(100), 
    ) AS NODE;
    
    CREATE TABLE likes (
      rating INTEGER
    ) AS EDGE;
    
    CREATE TABLE friendOf
      AS EDGE;
    
    /* Возможно в SQL Server 2019:
    ALTER TABLE likes
      ADD CONSTRAINT EC_LIKES CONNECTION (Person TO Cafe);
    */

    Основная специфика таких таблиц заключается в том, что в запросах к ним возможно использовать графовые паттерны с Cypher-подобным синтаксисом (впрочем, «*» и пр. пока не поддерживаются). Также на основе измерений производительности можно предположить, что способ хранения данных в этих таблицах отличен от механизма хранения данных в обычных таблицах и оптимизирован для выполнения подобных графовых запросов.


    SELECT Cafe.name
      FROM Person, likes, Cafe
      WHERE MATCH (Person-(friendOf)-(likes)->Cafe)
      AND Person.name = 'John';

    Более того, довольно трудно при работе с такими таблицами эти графовые паттерны не использовать, поскольку в обычных SQL-запросах для решения аналогичных задач потребуется предпринимать дополнительные усилия для получения системных «графовых» идентификаторов узлов ($node_id, $from_id, $to_id; по этой же причине запросы на вставку данных не приведены здесь как слишком громоздкие).


    Подводя итог описанию реализаций документной и графовой моделей в MS SQL Server, я бы отметил, что подобные реализации одной модели поверх другой не кажутся удачными в первую очередь с точки зрения языкового дизайна. Требуется расширять один язык другим, языки не вполне «ортогональны», правила сочетаемости могут быть довольно причудливы.


    Мультимодельные СУБД на основе документной модели


    В этом разделе хочется проиллюстрировать реализацию мультимодельности в документных СУБД на примере не наиболее популярной из них MongoDB (как было сказано, в ней есть лишь условно графовые операторы $lookup и $graphLookup, не работающие на шардированных коллекциях), а на примере более зрелой и «энтерпрайзной» СУБД MarkLogic.


    Итак, пусть коллекция содержит набор XML-документов следующего вида (хранить JSON-документы MarkLogic тоже позволяет):


    <Person INN="631803299804">
      <name>John</name>
      <surname>Smith</surname>
    </Person>

    Реляционная модель в MarkLogic


    Реляционное представление коллекции документов можно создать с помощью шаблона отображения (содержимым элементов value в примере ниже может быть произвольный XPath):


    <template xmlns="http://marklogic.com/xdmp/tde">
      <context>/Person</context>
      <rows>
        <row>
          <view-name>Person</view-name>
          <columns>
            <column>
              <name>SSN</name>
              <value>@SSN</value>
              <type>string</type>
            </column>
            <column>
              <name>name</name>
              <value>name</value>
            </column>
            <column>
              <name>surname</name>
              <value>surname</value>
            </column>
          </columns>
        </row>
      <rows>
    </template>

    К созданному представлению можно адресовать SQL-запрос (например, через ODBC):


    SELECT name, surname FROM Person WHERE name="John"

    К сожалению, созданное с помощью шаблона отображения реляционное представление доступно только для чтения. При обработке запроса к нему MarkLogic попытается использовать документные индексы. Прежде в MarkLogic были и ограниченные реляционные представления, целиком основанные на индексах и доступные на запись, но сейчас они считаются deprecated.


    Графовая модель в MarkLogic


    С поддержкой графовой (RDF) модели все обстоит примерно так же. Опять-таки с помощью шаблона отображения можно создать RDF-представление коллекции документов из примера выше:


    <template xmlns="http://marklogic.com/xdmp/tde">
      <context>/Person</context>
        <vars>
          <var>
            <name>PREFIX</name>
            <val>"http://example.org/example#"</val>
          </var>
        </vars>
      <triples>
        <triple>
          <subject><value>sem:iri( $PREFIX || @SSN )</value></subject>
          <predicate><value>sem:iri( $PREFIX || surname )</value></predicate>
          <object><value>xs:string( surname )</value></object>
        </triple>
        <triple>
          <subject><value>sem:iri( $PREFIX || @SSN )</value></subject>
          <predicate><value>sem:iri( $PREFIX || name )</value></predicate>
          <object><value>xs:string( name )</value></object>
        </triple>
      </triples>
      </template>

    К полученному RDF-графу можно адресовать SPARQL-запрос:


    PREFIX : <http://example.org/example#>
    SELECT ?name ?surname {
      :631803299804 :name ?name ; :surname ?surname .
    }

    В отличие от реляционной, графовую модель MarkLogic поддерживает еще двумя другими способами:


    1. СУБД может быть полноценным отдельным хранилищем RDF-данных (триплеты в нем будут называться managed в противоположность описанным выше extracted).
    2. RDF в специальной сериализации может быть попросту вставлен в XML- или JSON-документы (и триплеты тогда будут называться unmanaged). Вероятно, это такая альтернатива механизмам idref и пр.

    Хорошее представление о том, как «на самом деле» все устроено в MarkLogic, дает Optic API, в этом смысле оно низкоуровневое, хотя назначение его скорее обратное — попробовать абстрагироваться от используемой модели данных, обеспечить согласованную работу с данными в различных моделях, транзакционность и пр.


    Мультимодельные СУБД «без основной модели»


    На рынке также представлены СУБД, позиционирующие себя как изначально мультимодельные, не имеющие никакой унаследованной основной модели. К их числу относятся ArangoDB, OrientDB (c 2018 года компания-разработчик принадлежит SAP) и CosmosDB (сервис в составе облачной платформы Microsoft Azure).


    На самом деле «основные» модели в ArangoDB и OrientDB есть. Это в том и в другом случае собственные модели данных, являющиеся обобщениями документной. Обобщения заключаются в основном в облегчении возможности производить запросы графового и реляционного характера.


    Эти модели являются в указанных СУБД единственно доступными для использования, для работы с ними предназначены собственные языки запросов. Безусловно, такие модели и СУБД перспективны, однако отсутствие совместимости со стандартными моделями и языками делает невозможным использование этих СУБД в унаследованных системах — замену ими уже используемых там СУБД.


    Про ArangoDB и OrientDB на Хабре уже была замечательная статья: JOIN в NoSQL базах данных.


    ArangoDB


    ArangoDB заявляет поддержку графовой модели данных.


    Узлы графа в ArangoDB — это обычные документы, а ребра — документы специального вида, имеющие наряду с обычными системными полями (_key, _id, _rev) системные поля _from и _to. Документы в документных СУБД традиционно объединяются в коллекции. Коллекции документов, представляющих ребра, в ArangoDB называются edge-коллекциями. К слову, документы edge-коллекций — это тоже документы, поэтому ребра в ArangoDB могут выступать также и узлами.


    Исходные данные

    Пусть у нас есть коллекция persons, документы которой выглядят так:


    [
      {
        "_id"  : "people/alice" ,
        "_key" : "alice" ,
        "name" : "Алиса"
      },
      {
        "_id"  : "people/bob" ,
        "_key" : "bob" ,
        "name" : "Боб"  
      }
    ]

    Пусть также есть коллекция cafes:


    [
      {
        "_id" : "cafes/jd" ,
        "_key" : "jd" ,
        "name" : "Джон Донн"  
      },
      {
        "_id" : "cafes/jj" ,
        "_key" : "jj" ,
        "name" : "Жан-Жак"
      }
    ]

    Тогда коллекция likes может выглядеть следующим образом:


    [
      {
        "_id" : "likes/1" ,
        "_key" : "1" ,
        "_from" : "persons/alice" ,
        "_to" : "cafes/jd",
        "since" : 2010 
      },
      {
        "_id" : "likes/2" ,
        "_key" : "2" ,
        "_from" : "persons/alice" ,
        "_to" : "cafes/jj",
        "since" : 2011 
      } ,
      {
        "_id" : "likes/3" ,
        "_key" : "3" ,
        "_from" : "persons/bob" ,
        "_to" : "cafes/jd",
        "since" : 2012 
      }
    ]

    Запросы и результаты

    Запрос в графовом стиле на используемом в ArangoDB языке AQL, возвращающий в человекочитаемом виде сведения о том, кому какое кафе нравится, выглядит так:


    FOR p IN persons
      FOR c IN OUTBOUND p likes
      RETURN { person : p.name , likes : c.name }

    В реляционном стиле, когда мы скорее «вычисляем» связи, а не храним их, этот запрос можно переписать так (к слову, без коллекции likes можно было бы обойтись):


    FOR p IN persons
      FOR l IN likes
      FILTER p._key == l._from
        FOR c IN cafes
        FILTER l._to == c._key
        RETURN { person : p.name , likes : c.name }

    Результат в обоих случаях будет один и тот же:


    [
      { "person" : "Алиса" , likes : "Жан-Жак" } ,
      { "person" : "Алиса" , likes : "Джон Донн" } ,
      { "person" : "Боб" , likes : "Джон Донн" }
    ]

    Еще запросы и результаты

    Если кажется, что формат результата выше характерен больше для реляционной СУБД, чем для документной, можно попробовать такой запрос (либо можно воспользоваться COLLECT):


    FOR p IN persons
      RETURN {
        person : p.name,
        likes : (
          FOR c IN OUTBOUND p likes
          RETURN c.name
        )
    }

    Результат будет иметь следующий вид:


    [
      { "person" : "Алиса" , likes : ["Жан-Жак" , "Джон Донн"]  } ,
      { "person" : "Боб" , likes : ["Джон Донн"] }
    ]

    OrientDB


    В основе реализации графовой модели поверх документной в OrientDB лежит возможность полей документов иметь помимо более-менее стандартных скалярных значений еще и значения таких типов, как LINK, LINKLIST, LINKSET, LINKMAP и LINKBAG. Значения этих типов — ссылки или коллекции ссылок на системные идентификаторы документов.


    Присваиваемый системой идентификатор документа имеет «физический смысл», указывая позицию записи в базе, и выглядит примерно так: @rid : #3:16. Тем самым значения ссылочных свойств — действительно скорее указатели (как в графовой модели), а не условия отбора (как в реляционной).


    Как и в ArangoDB, в OrientDB ребра представляются отдельными документами (хотя если у ребра нет своих свойств, его можно сделать легковесным, и ему не будет соответствовать отдельный документ).


    Исходные данные

    В формате, приближенном к формату дампа базы OrientDB, данные из предыдущего примера для ArangoDB выглядели бы примерно так:


    [
         {
          "@type": "document",
          "@rid": "#11:0",
          "@class": "Person",
          "name": "Алиса",
          "out_likes": [
            "#30:1",
            "#30:2"
          ],
          "@fieldTypes": "out_likes=LINKBAG"
        },
        {
          "@type": "document",
          "@rid": "#12:0",
          "@class": "Person",
          "name": "Боб",
          "out_likes": [
            "#30:3"
          ],
          "@fieldTypes": "out_likes=LINKBAG"
        },
        {
          "@type": "document",
          "@rid": "#21:0",
          "@class": "Cafe",
          "name": "Жан-Жак",
          "in_likes": [
            "#30:2",
            "#30:3"
          ],
          "@fieldTypes": "in_likes=LINKBAG"
        },
        {
          "@type": "document",
          "@rid": "#22:0",
          "@class": "Cafe",
          "name": "Джон Донн",
          "in_likes": [
            "#30:1"
          ],
          "@fieldTypes": "in_likes=LINKBAG"
        },
        {
          "@type": "document",
          "@rid": "#30:1",
          "@class": "likes",
          "in": "#22:0",
          "out": "#11:0",
          "since": 1262286000000,
          "@fieldTypes": "in=LINK,out=LINK,since=date"
        },
        {
          "@type": "document",
          "@rid": "#30:2",
          "@class": "likes",
          "in": "#21:0",
          "out": "#11:0",
          "since": 1293822000000,
          "@fieldTypes": "in=LINK,out=LINK,since=date"
        },
        {
          "@type": "document",
          "@rid": "#30:3",
          "@class": "likes",
          "in": "#21:0",
          "out": "#12:0",
          "since": 1325354400000,
          "@fieldTypes": "in=LINK,out=LINK,since=date"
        }
      ]

    Как мы видим, вершины тоже хранят сведения о входящих и исходящих ребрах. При использовании Document API за ссылочной целостностью приходится следить самому, а Graph API берет эту работу на себя. Но посмотрим, как выглядят обращение к OrientDB на «чистых», не интегрированных в языки программирования, языках запросов.


    Запросы и результаты

    Запрос, аналогичный по назначению запросу из примера для ArangoDB, в OrientDB выглядит так:


    SELECT name AS person_name, OUT('likes').name AS cafe_name
       FROM Person
       UNWIND cafe_name

    Результат будет получен в следующем виде:


    [
      { "person_name": "Алиса", "cafe_name": "Джон Донн" },
      { "person_name": "Алиса", "cafe_name": "Жан-Жак" },
      { "person_name": "Боб",  "cafe_name": "Жан-Жак" }
    ]

    Если формат результата опять кажется чересчур «реляционным», нужно убрать строку с UNWIND():


    [
      { "person_name": "Алиса", "cafe_name": [ "Джон Донн", "Жан-Жак" ] },
      { "person_name": "Боб",  "cafe_name": [ "Жан-Жак" ' }
    ]

    Язык запросов OrientDB можно охарактеризовать как SQL c Gremlin-подобными вставками. В версии 2.2 появилась Cypher-подобная форма запроса, MATCH :


    MATCH {CLASS: Person, AS: person}-likes->{CLASS: Cafe, AS: cafe}
    RETURN person.name AS person_name, LIST(cafe.name) AS cafe_name
    GROUP BY person_name

    Формат результата будет таким же, как в предыдущем запросе. Подумайте, что нужно убрать, чтобы сделать его более «реляционным», как в самом первом запросе.


    Azure CosmosDB


    В меньшей степени сказанное выше об ArangoDB и OrientDB относится к Azure CosmosDB. CosmosDB предоставляет следующие API доступа к данным: SQL, MongoDB, Gremlin и Cassandra.


    SQL API и MongoDB API используются для доступа к данным в документной модели. Gremlin API и Cassandra API — для доступа к данным соответственно в графовой и колоночной. Данные во всех моделях сохраняются в формате внутренней модели CosmosDB: ARS («atom-record-sequence»), которая также близка к документной.



    Но выбранная пользователем модель данных и используемый API фиксируются в момент создания аккаунта в сервисе. Невозможно получить доступ к данным, загруженным в одной модели, в формате другой модели, что иллюстрировалось бы примерно таким рисунком:



    Тем самым мультимодельность в Azure CosmosDB на сегодняшний день представляет собой лишь возможность использовать несколько баз данных, поддерживающих различные модели, от одного производителя, что не решает всех проблем многовариантного хранения.


    Мультимодельные СУБД на основе графовой модели?


    Обращает на себя внимание тот факт, что на рынке пока нет мультимодельных СУБД, имеющих в основе графовую модель (если не считать мультимодельностью поддержку одновременно двух графовых моделей: RDF и LPG; см. об этом в предыдущей публикации). Наибольшие затруднений вызывает реализация поверх графовой модели документной, а не реляционной.


    Вопрос о том, как реализовать поверх графовой модели реляционную, рассматривался еще во времена становления этой последней. Как говорил, например, Дэвид Макговерен:


    There is nothing inherent in the graph approach that prevents creating a layer (e.g., by suitable indexing) on a graph database that enables a relational view with (1) recovery of tuples from the usual key value pairs and (2) grouping of tuples by relation type.

    При реализации же документной модели поверх графовой нужно иметь в виду, например, следующее:


    • Элементы JSON-массива считаются упорядоченными, исходящие из вершины ребра графа — нет;
    • Данные в документной модели обычно денормализованы, хранить несколько копий одного и того же вложенного документа все же не хочется, а идентификаторов у поддокументов обычно нет;
    • С другой стороны, идеология документных СУБД в том и заключается, что документы являются готовыми «агрегатами», которые не нужно каждый раз строить заново. Требуется обеспечить в графовой модели возможность быстро получить подграф, соответствующий готовому документу.

    Немного рекламы

    Автор статьи имеет отношение к разработке СУБД NitrosBase, внутренняя модель которой является графовой, а внешние модели — реляционная и документная — являются её представлениями. Все модели равноправны: практически любые данные доступны в любой из них с использованием естественного для неё языка запросов. Более того, в любом представлении данные могут быть изменены. Изменения отразятся во внутренней модели и, соответственно, в других представлениях.


    Как выглядит соответствие моделей в NitrosBase — опишу, надеюсь, в одной из следующих статей.


    Заключение


    Надеюсь, что общие контуры того, что называется мультимодельностью, стали читателю более-менее ясны. Мультимодельными называются достаточно разные СУБД, и «поддержка нескольких моделей» может выглядеть по-разному. Для понимания того, что называют «мультимодельностью» в каждом конкретном случае, полезно ответить на следующие вопросы:


    1. Идет ли речь о поддержке традиционных моделей или же о некоей одной гибридной модели?
    2. «Равноправны» ли модели, или одна из них является подлежащей для других?
    3. «Безразличны» ли модели друг другу? Могут ли данные, записанные в одной модели, быть прочитанными в другой или даже перезаписаны?

    Думаю, на вопрос об актуальности мультимодельных СУБД уже можно дать положительный ответ, но интересен вопрос о том, какие именно их разновидности будут более востребованы в ближайшее время. Похоже, более востребованы будут мультимодельные СУБД, поддерживающие традиционные модели, в первую очередь, реляционную; популярность же мультимодельных СУБД, предлагающих новые модели, сочетающие в себе достоинства различных традиционных, — дело более отдаленного будущего.



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

    Используете ли вы мультимодельные СУБД?

    • 40,9%Не используем, храним все в одной СУБД и в одной модели18
    • 34,1%Используем мультимодельные возможности традиционных СУБД15
    • 34,1%Практикуем многовариантное хранение (polyglot persistence)15
    • 18,2%Используем новые мультимодельные СУБД (Arango, Orient, CosmosDB)8

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +1
      Дополнения по Microsoft SQL Server:
      — основная реализация документ-ориентированной модели не JSON, а XML (с версии 2005): нативное хранение, индексация, язык запросов XQuery, поддержка XSD-схем документов. JSON действительно введен в версии 2016 скорее для промежуточного хранения и удобства;
      — поддерживается не указанная в сравнительном списке модель «ключ-значение» на основе механизма хеш-таблиц в памяти;
      — поддерживается (тoже не указана) многомерная модель — гиперкубы (SQL Server Analysis Services), была еще до версии 2005 под названием MS OLAP.
        +1
        Да, спасибо! В случае с MarkLogic тоже был выбор про что рассказывать: про XML или про JSON. Решил тут про JSON, там про XML.

        Поддержку «key-value» почти для всех СУБД обошел вниманием, упоминаю ее только если совсем нечего сказать.
          +2
          JSON как был легким форматом для сериализации обьектов, так по сути им и остался. Понадобится обеспечение целостности, валидация — пиши код в приложении, языки запросов специфичны для СУБД, стандарты фактически отсутствуют, RFC — предел мечтаний.
          XML изначально проектировался для хранения документов, обеспечения целостности и извлечения информации по запросам, стандарт устоялся и щироко используется в корпоративном софтостроении.
          Сходство в том, что обе модели основаны на теоретико-графовой иеррхической модели. Но ограничения иерархий тоже известны с 1960-х годов, когда переходили к сетевым и множественным моделям данных.
          Более подробно есть в статье "Classification of data models in DBMS" на researchgate и в книжке "СУБД для программиста" (пардон за продакт-плейсмент)
        +1
        документы являются готовыми «агрегатами», которые не нужно каждый раз строить заново

        Ну как это «не нужно»? А изменения как вносить? Либо говорим прямо — нас устроит реляционная БД с возможностью хранить длинные строки, куда мы и положим все эти не редактируемые документы. Ну и напомню — длинные строки в реляционных БД есть ещё со времён царя Гороха. Но тогда зачем новые модели БД?
          +1
          Перефразируя известный баннер на авто: «Внесение изменений в данные придумали адепты реляционных БД!» :)
            0

            Сильных жалоб на трудности с тем, чтобы изменять документы в документных СУБД, вроде бы нет, см., например, db.collection.update() в MongoDB.


            P.S. Понял, это был сарказм.

            +1

            Термин «агрегаты» взят из второй главы NoSQL Distilled Садаладжа и Фаулера, там много об этом. Сам термин мне не нравится, больше нравятся «композиты», в том числе с точки зрения значений слов в UML.


            По сути, речь идет о денормализации. Поскольку производительность операций соединения в РСУБД не очень высока, давайте не будем их выполнять при каждом запросе. Будем хранить пакеты данных с предвыполненными такими операциями в готовом к отправке формате. Если что, клиент доразберет.


            Поскольку все нужные соединения как бы уже выполнены, давайте разучимся их хоть как-то выполнять. Тогда и масштабироваться будет легко, а то межшардовые джойны — ужас-ужас.


            Однако аналоги других реляционных операций, например, выборки по значениям полей, делать будем уметь, а то нас назовут хранилищем «key-value». Особых же проблем с тем, чтобы изменять документы, удовлетворяющие условию выборки, в документных СУБД нет, см. следующий комментарий.


            Примерно такова идеология документных СУБД в утрированном виде. Т. е. «строить» в цитированной вами фразе означало что-то типа «собирать», а не «отбирать» или «изменять».

              +1
              соединения как бы уже выполнены

              именно, что «как бы выполнены». Проблема иерархической модели (к коим относится документ-ориентированная) в необходимости дублирования данных в иерархиях. Или хранить логические ссылки (по коду, ID и т.п.) на другие иерархии с неизбежными соединениями в запросах.

              Простейший пример, две иерархии (коллекции в терминах монги) заказов и отгрузок хранят данные о клиентах. Либо дублирование, либо третья иерархия клиентов со ссылками. «Нормализация» в рамках иерархической модели. Привет из 1960-х и от IBM IMS персонально :)
                0
                >> Поскольку производительность операций соединения в РСУБД не очень высока, давайте не будем их выполнять при каждом запросе

                С этим отлично справляются РСУБД (храним XML/JSON в строках).

                >> Поскольку все нужные соединения как бы уже выполнены, давайте разучимся их хоть как-то выполнять. Тогда и масштабироваться будет легко

                Отказ от джойнов «вообще» — движение в каменный век. В РСУБД можно сделать таблицу со строками-документами и не джойнить к ней постоянно, а только в редких случаях. В результате имеем все удобства и ничего не тормозит.

                >> Особых же проблем с тем, чтобы изменять документы, удовлетворяющие условию выборки, в документных СУБД нет

                Это вы заявляете на основе просто наличия самой возможности что-то поправить, но какова скорость правки? Для неё нужно распарсить документ, изменить нужное значение, снова сериализовать, ну а потом, понятно, сохранить. То есть на лицо лишняя нагрузка на процессор, плюс лишняя нагрузка на диск в случае приличного размера документов (а это — большинство из них). В РСУБД этого всего просто нет.

                >> «строить» в цитированной вами фразе означало что-то типа «собирать»

                Я так и понимал это слово, когда комментировал. Суть в необходимости парсить, а потом снова сериализовать документы минимум на несколько десятков килобайт, а то и на мегабайты.

                ЗЫ. Я вообще не против нового, но оно обязано доказывать свою ценность.
                  +2

                  Мне не хотелось бы сваливаться в комментариях в дискуссии на тему «SQL vs. NoSQL». Сойдемся на том, что люди используют (не обязательно по соображениям производительности) и то, и другое, причем порой одновременно. Тогда возникают две основных проблемы: сложность управления всем этим хозяйством и невозможность транзакций в такой гетерогенной среде. СУБД, называющие себя мультимодельными, пытаются их как-то решить. Некоторые — ценой ухудшения производительности по сравнению со специализированными «одномодельными». А по отношению к сторонам спора «SQL vs. NoSQL» я стараюсь выдерживать нейтральное отношение.


                  С этим отлично справляются РСУБД
                  Отказ от джойнов «вообще» — движение в каменный век.

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


                  Для сравнения, в графовых СУБД сведения о «соединенных» вершинах являются непосредственно хранимыми, поэтому запросы графового характера могут в них выполняться быстрее. В конце концов, не нужно пытаться быть большим католиком, чем сам папа. А папа говорил:


                  It may be argued that in some applications the problems have an immediate natural formulation in terms of networks. This is true of some applications, such as studies of transportation networks, power-line networks, computer design, and the like. We shall call these network applications and consider their special needs later.

                  Ну а документные СУБД решают проблему джойнов денормализацией и дублированием, да.


                  Это вы заявляете на основе просто наличия самой возможности что-то поправить, но какова скорость правки? Для неё нужно распарсить документ, изменить нужное значение, снова сериализовать, ну а потом, понятно, сохранить.

                  Это в SQL Server так, причем, хочется надеяться, временно. В документной СУБД документ уложен в какую-то структуру данных, хранится не как текст. Есть индексы по полям, работой с ними по сути можно и ограничиться, если пользователь просто хочет поменять себе год рождения :).


                  Например, так обстоят дела в MongoDB: https://docs.mongodb.com/manual/core/write-performance/. И в статьях с жалобами на документные СУБД жалобы на производительность модификации записей занимают не первое место. Первое место занимают джойны, ну а чего хотели-то?

                    +1
                    >> Мне не хотелось бы сваливаться в комментариях в дискуссии

                    И мне туда же.

                    Но джойны в РСУБД ликвидируются просто (если нужно), а вот реляционная модель со всеми удобствами в нереляционных базах нереализуема (ибо очень дорого). В сумме РСУБД может не хуже NoSQL, а NoSQL не может как РСУБД.

                    Есть отдельные узкие ниши, где отказ от РСУБД может ускорить некоторые виды обработки данных, но ускорение получается так себе (хотя может кому-то важно хотя бы 20-40% роста в обмен на отказ от всем привычного и гибкого). А в плане удобства работы с документами — просто используем приличный ORM и опять NoSQL становится ненужным.

                    Но да, я не спора ради, я пробую простую идею донести — в массовом применении РСУБД объективно лучше, а массовая популяризация NoSQL ради каких-то узких ниш — совершенно не оправдана.
                      +1
                      в массовом применении РСУБД объективно лучше, а массовая популяризация NoSQL ради каких-то узких ниш — совершенно не оправдана.

                      Нисколько не споря с тезисом (весьма нелепо спорить с тем, в чём сам убеждён) хочу лишь заметить что вы недооцениваете роль моды в ИТ.
                        0
                        Такое поветрие формируется намеренно, сначала юные архитекторы убеждают боссов использовать новый подход, потом выясняется, что специалистов по нему нет и большие конторы начинают вкладываться в популяризацию подхода. В итоге стихийно порождается много шума, но обоснованность всего этого зоопарка покоится, по сути, на мнении одного единственного экспериментатора — того самого архитектора, или просто человека с возможностями влиять на (часто случайный) выбор во внутренней кухне корпорации.

                        Хотя аналогия с модой, безусловно, есть. Но популяризируют продукт именно деньги корпораций, и лишь потому, что в их конкретной обстановке был выбран конкретный продукт. То есть бежать за этой «модой» — неэффективно, ибо выбор не основан на чём-то рациональном.

                        Среди людей принято увлекаться чем-либо, от религии до чайной церемонии, но религию обычно не называют модой, поэтому и выбор СУБД (и технологий вообще) — то же увлечение, которое даже может остаться на всю жизнь. Хотя если нравится, можно и модой обозвать :)
                          0
                          В данном случае, разумеется, речь про явление. Оно не полностью тождественно моде (как не полностью тождественно религии, философскому учению и т.п.), но весьма на неё похоже (в первую очередь именно отсутствием чёткой логической мотивации выбора).
                        0

                        Чем же реляционная модель объективно лучше графовой?

                          0
                          Областью применимости.

                          Переведите разработку инфосистем на графы, тогда их область применимости станет более подходящей.
                            +1
                            user_man, по-видимому, имел в виду, «субъективно». Просто разработчикам удобно при небольшом количестве связей (короткие JOIN), когда на переходе по ним и время теряется не сильно, и SQL запросы получаются не гигантские. До 3-4 join это как-то работает. В этом случае — да, лучше.
                              0

                              И чем же запрос вида


                              select
                                  users.id ,
                                  users.name ,
                                  images.href ,
                                  images.width ,
                                  images.height
                              from
                                  images,
                                  users
                              where
                                  users.id = images.user_id

                              проще и быстрее такого


                              select from users
                              fetchplan
                                  *:-2
                                  id:0
                                  name:0
                                  images.href:0
                                  images.width:0
                                  images.height:0

                              ?

                                0
                                В плане «быстрее» — у вас больше джойнов. При этом физическая реализация может оптимизировать джойны, но тогда ухудшается что-то другое, например внесение изменений.
                                  0

                                  У меня вообще нет джойнов.

                                    0

                                    а как же users.id = images.user_id ?

                                      0

                                      Это в реляционной субд. В графовой джойнов нет.

                                        0
                                        В графовой джойнов нет.

                                        Кстати, в общем виде такое утверждение всё-таки не совсем верно. Оно верно при чисто навигационном стиле запросов, который не всегда возможен и не всегда оптимален.


                                        См., например, статью «How to avoid costly traversals with join hints» в базе знаний Neo4j. Пример запроса оттуда:


                                        MATCH (me:Person {name:'Me'})-[:FRIENDS_WITH]-(friend)-[:LIKES]->(a:Artist)<-[:LIKES]-(me)
                                        USING JOIN on a
                                        RETURN a, count(a) as likesInCommon
                                          +1

                                          Я говорил про приведённые мной два запроса. Не про вообще, конечно же.

                        +2
                        Я вообще не против нового, но оно обязано доказывать свою ценность.

                        Ну, строго говоря, документо-ориентированные БД — это совсем не новое (и появились они ДО реляционных, которые, в свою очередь, как раз и решали многие проблемы предшественников) :)
                          0
                          Я бы назвал те древние подходы файло-ориентированными. Хотя не исключаю, что где-то в тёмных и мрачных пещерах с очень умными неандертальцами проскакивал шаблон хранения структурированных данных, но не на основе реляционной модели. Только это было исключением. Массово же — файлы. Да ещё с микроскопической скоростью обработки и на ленточных носителях…
                            +1
                            Называть их можно как угодно. Тогда это называли сетевыми и иерархическими БД.
                            Но было это не только в эпоху ленточек, но уже и во вполне себе «дисковые времена».
                    +2
                    Есть еще продукты InterSystems, лидер в Объектно ориентированных. В основе хранения много-мерный глобал (переменная) хранимый а базе данных с помощью B*-tree. Поверх которого добавлен слой из объектов и реляционная модель. Так же уже есть и варинт с DocumentDB.
                      +2

                      Да, там перед таблицей я говорю «наиболее важными будем считать реляционную, документную и графовую модели» ввиду невозможности объять необъятное.


                      Что до объектной модели… Тот же Gartner в «IT Market Clock for DBMSs 2019»» предсказывает ей скорую кончину (а мультимодельным СУБД, наоборот, расцвет).


                      Картинка с циферблатом


                      Как человеку, занимавшемуся информатизацией здравоохранения, мне будет Caché немного жаль :-). Однако вот OrientDB тоже заявляет о поддержке объектной модели.

                        +2
                        Не вижу причин, для беспокойства за Caché и есть уже более свежий новый продукт IRIS. У нас все равно есть мультимодельность, и объектно ориентированность лишь слой. Как раз наличие большого количества уже работающих проектов, не даст сгинуть совсем. А новые проекты так же еще появляются, в том числе и в здравоохранении.
                        0
                        В SQL Server реляционная модель тоже реализована поверх B-tree, но к нему нет прямого доступа, как в Caché.
                        +1
                        В дополнение к статье.
                        Еще одна современная архитектура/паттерн: Data Lake — хранилище «сырых» разнородных данных (структурированных, полуструктурированных, неструктурированных). Применяется для работы с необработанными данными, может поддерживать динамические схемы хранения. Особенно незаменимо при исследовании данных.

                        Мне кажется, это стоит упоминания, если мы говорим про мультимодельные ИС.
                          0

                          Ну, это немного другая разновидность того, что в совокупности можно назвать конвергентными платформами хранения или как-то так. Наверное, стоило бы в статье указать на отличия этих разновидностей. Про нестуктурированные данные вы сами говорите, про преимущественно не-OLTP характер задач тоже :-).

                          0
                          Использование JSON и/или XML в СУРБД это прямой путь к проблемам.
                          На текущем проекте так сделали на MS SQL. Тормоза приотличнейшие.
                            0
                            Успешно решал подобную проблему у клиента еще на версии 2005. Они вовремя спохватились, не имея в штате специалистов по СУБД и сделав нагрузочные тесты на ранней стадии. Усеченный пример есть в книжке (в профиле).
                            +1

                            mad_nazgul, я бы за любую РСУБД так не сказал, может, где и можно побороться.


                            С XML и JSON тоже дела могут обстоять не одинаково. Например, в SQL Server для XML есть индексы, а для JSON нет.


                            Какие-то рекомендации по увеличению производительности при работе с c JSON в SQL Server 2017 были по второй ссылке в том разделе статьи (извиняюсь, она сначала дублировала первую, исправил это).

                              +1
                              Edge constraints не в версии 2019 появились?
                                0

                                Да, спасибо, закомментировал.

                                +1

                                Рекомендую также обратить внимание на мультимодельные БД Virtuoso и GRAKN.

                                  0

                                  С OpenLink Software создателей NitrosBase связывают достаточно давние напряженные отношения :-). Подробнее на этот и следующий ваши комментарии отвечу попозже.

                                    +2

                                    В общем, спасибо еще раз за замечание, я наконец-то созрел дать взвешенный ответ.


                                    GRAKN, конечно, интересен. В первую очередь тем, что является единственным отличным от триплсторов более-менее популярным в наши дни представителем того, что Дейт называет «системами баз данных, основанными на логике». В их мультимодельности я бы посомневался… Да, они говорят, что поддерживают реляционную модель, но это не традиционная реляционная модель, а ее, гм, обобщение. Впрочем, тот же известный нам с вами K. I. любит утверждать, что графовая модель тоже реляционная, а Кодд, стало быть, просто узурпировал название. Не согласен с этим, тисну скоро один перевод на эту тему.


                                    Ну и главное, про Virtuoso. Он немного ломает всю классификацию, поэтому не стал его включать (зато для любителей RDF рассказывается про MarkLogic). Базовая модель в Virtuoso реляционная, по сути это такой EAV на стероидах, однако ведущей реляционной СУБД он не является. Логика же истории была к том, что мономодельные СУБД тех времен пытались стать мультимодельными. Virtuoso же был мультимодельным уже тогда. Было принято решение в качестве «субстрата» для хранения RDF использовать реляционную модель (ну а что, разработчики КИС до сих пор всё в нее укладывают), а заодно разработать классную реляционную СУБД. Эх, сейчас так уже не делают, а берут в качестве нижележащей системы хранения RocksDB (писал об этом тут).


                                    Если же о причинах не риторических… Когда поддерживаются и реляционная модель, и RDF, то хочется каких-то содержательных отношений между ними, а не просто чтобы первая была субстратом для второй. Адепты RDF люди избалованные, им хочется чего-то вроде RDB2RDF DM в обе стороны. Кстати, что-то подобное есть в NitrosBase. А когда отношение между данными в двух моделях заключается в банальном EAV, не очень ясна практическая применимость этих вкусностей Virtuoso наподобие SPASQL (возможность сочетать SQL- и SPARQL-запросы), пополнения SQL-таблиц результатами присоединения следствий и пр.


                                    И самое главное… Реализованная через EAV мультимодельность кажется мне причиной багов Virtuoso, связанных с поддержкой property paths. Она на самом деле в Virtuoso весьма плохая. Предполагаю, что потому, что пришлось ее реализовывать через механизм транзитивных SQL-запросов.


                                    Disclaimer

                                    Но можно дипломатично согласиться, что Virtuoso просто опередил свое время. OpenLink поспешили реализовать property paths, но в SPARQL 1.1 те были стандартизованы не совсем так, как реализованы в Virtuoso, что и стало источником проблем. Но если посмотреть на работу SPARQL 1.2 CWG, то можно увидеть в вопросе о property paths некоторое тяготение в сторону Virtuoso. Но больше все предвкушают SPARQL 2, заточенный на работу с RDF*. Сможет ли Virtuoso его в принципе поддержать — не знаю. Про RDF* я немного написал тут.

                                    0

                                    А как у вас хранятся графы? И как делаются по ним выборки?

                                      +2

                                      Для хранения сведений о связях между ребрами используется оригинальный sparse link index, довольно далекий от B-деревьев и их производных. Можно сказать, что он быстрый, как в специализированных графовых библиотеках, но быстрый еще и на запись. А для хранения скалярных атрибутов используются (когда используются) довольно стандартные индексы.


                                      Я много рассказать не могу, вот в открытом доступе информация в объеме и формате патентной заявки.

                                      +1

                                      Коллеги подкинули ссылку на статью C. Zhang, J. Lu, P. Xu, Y. Chen. UniBench: A Benchmark for Multi-Model Database Management Systems из сборника проходившей год назад в Рио-де-Жанейро 10th TPC Technology Conference on Performance Evaluation and Benchmarking (боковой трек в VLDB 2018).


                                      Табличка из нее, похожая на приведенную в посте, предлагает классификацию мультимодельных СУБД. Не все в этой табличке согласуется с написанным в посте.


                                      Таблица

                                        +1

                                        Все четверо из Хельсинкского университета. На финско-китайской границе всё спокойно — был такой анекдот.

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

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