Запись об этом появилась в блоге AWS в начале августа. Эталонная реализация выложена на GitHub.



Почему это важно?


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


С этой точки зрения интересно, какие именно решения по интеграции данных предлагаются в облаках, поскольку эти решения заведомо должны быть передовыми и идеологически выверенными. И вот три недели назад Amazon предложил решение класса NoETL — обратно совместимый с SQL-92 язык для запросов к данным в различных форматах.


Язык PartiQL идейно схож с SQL++, получившим высокую оценку Д. Чемберлина, одного из соавторов SQL (Чемберлин даже написал учебник по SQL++). Сходство двух языков неслучайно: автор обоих — один и тот же человек, Яннис Папаконстантину.


К слову, Couchbase, в которой поддержка SQL++ недавно была реализована, обещает рассмотреть возможность поддержать PartiQL, а пока что PartiQL частично поддерживается в Amazon S3 Select, в Amazon Redshift Spectrum и используется во внутренних системах Amazon.


Технические детали


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


Данные

В абстрактной модели PartiQL эти реляционные данные будут выглядеть так:


{ 
   "silovikicat": { 
        "people": <<
            { "name": "Алиса", "likes": "Жан-Жак" } ,
            { "name": "Боб",   "likes": "Джон Донн" }
        >>
    }
}

Каждому кортежу отношения соответствует плоский (со скалярными значениями полей) объект.


Использование << и >> вместо [ и ] означает, что элементы коллекции не упорядочены (как это и положено в реляционной модели кортежам отношения). Не такое уж большое расширение JSON по сравнению с Amazon Ion, но если не нравится, можно использовать обычные массивы вместо мультимножеств.


Запрос

Запрос на PartiQL выглядит так:


SELECT p.name AS person, p.likes AS cafe
FROM silovikicat.people AS p
WHERE p.name = "Алиса"

Результат

Результат будет таким:


<<
  {
    "person" : "Алиса", "cafe": "Жан-Жак"
  }
>>

Если вам показалось, что точка в полном идентификаторе таблицы немного двусмысленна, вы правы. Оператор «.» получает по ключу значение и позволяет обходить иерархические структуры, если они вдруг оказываются значениями полей. Можно строить цепочки любой длины. Если по пути попадется массив, можно получить элемент по индексу (и [*] тоже разрешено). Кажется, пока ничего нового по сравнению с поддержкой JSONPath в реляционных СУБД, умеющих работать с JSON?


Тогда попробуем кое-что посложнее. Допустим, значением likes является массив, и упорядочение элементов имеет некоторое значение. Хотелось бы не потерять это упорядочение в результатах.


Данные
{ 
   "silovikicat": { 
        "people": <<
            {
                "name": "Алиса",
                "likes": [
                    { "name": "Жан-Жак" },
                    { "name": "Джон Донн" } 
                ]
            } ,
            {
                "name": "Боб",
                "likes": [ 
                    { "name": "Джон Донн" } 
                ] 
            }
        >>
    }
}

Запрос
SELECT p.name AS person_name, 
       o AS cafe_priority
       c.name AS cafe_name, 
FROM silovikicat.people AS p, 
     p.likes AS c AT o
WHERE p.name = 'Алиса'
ORDER BY cafe_priority ASC

Результат
[
  {
    "person_name": "Алиса", "cafe_priority": 0, "сafe_name": "Жан-Жак"
  },
  {
    "person_name": "Алиса", "cafe_priority": 1, "cafe_name": "Джон Донн"
  }
]

Мы видим, что иерархические данные являются практически сущностями первого класса:


  • Возможно указывать маршруты обхода во FROM, при этом они ведут себя вполне «таблично» — могут быть соединены и пр. Если, например, конец первого из двух записанных через запятую маршрутов совпадает с началом второго, это, по сути, JOIN по условию вложенности объектов.
  • Ключевое слово AT — в отличие, например, от тильды в JSONPath Plus — возвращает ключи «в привязке» к значениям, то есть отношение в смысле реляционной модели.

UPDATE

Суть PartiQL в том, что маршрут обхода иерархической структуры формирует таблицу: первый столбец — где были на первом шаге, второй — где на втором и т. д. Чем столбец правее, тем больше в нем уникальных значений. В терминах MS SQL Server маршрут — это такой rowset provider. Получаемые таблицы можно соединять (JOIN) друг с другом и с обычными таблицами.


Эта одна простая концепция заменяет половину стандарта SQL/JSON со всеми его функциями, врезаемыми в декларативный язык запросов.


В принципе, это всё, что нужно знать о PartiQL, если есть возможность немного доразобрать ответ на клиенте. Если хочется поупражняться в конструировании JSON и выворачивании его наизнанку на стороне сервера, есть PIVOT (работает похоже на сводные таблицы в Excel), UNPIVOT и GROUP AS.


Может возникнуть вопрос: но ведь эти JSON-данные бессхемны, в различных кортежах по одному ключу могут быть доступны данные различной структуры. Если данные не совсем совпадают с их схемой в голове, PartiQL возвращает значение MISSING. Это такой альтернативный NULL. Но можно и явно проверять, с чем имеешь дело, с помощью CASE WHEN cafe IS TUPLE… и т. п.


Что дальше?


На наших глазах происходит конвергенция сервисов хранения данных. Что нас ждет в финале? Вероятно, полная их конвергентность. Этому есть и теоретическое обоснование, и эмпирическое.


Использование нескольких облачных сервисов хранения данных — тоже polyglot persistence, пусть и в облачном варианте. Однако известно, что на смену polyglot persistence идет мультимодельность. Что даст клиентам облачного провайдера облачная версия мультимодельности?


  • Безопасность. Необходимость управлять пользователями сразу нескольких хранилищ повышает риск ошибки, чему, вероятно, служит подтверждением инцидент с утечкой данных Capital One.
  • Транзакционность, которая в гетерогенной среде проблематична, но которую хотелось бы иметь в связи со всеобщим движением от OLAP к HTAP.

В маркетинге DataStax это называются single entry point и right-now economy соответственно, однако о чем DataStax умалчивает — это о том, что мультимодельность выгодна не только клиенту сервиса, но и поставщику. Обеспечение enterprise-характеристик сервиса хранения, пусть эта задача в облаке и автоматизирована в значительной степени, всё же легче для одного сервиса, чем для нескольких. That would save you a lot of money, Mr. Bezos, please call me.


Ну а эмпирическим подтверждением того, что направление движения — мультимодельность, является лучшая её поддержка основном конкурентом — Azure, который второй год подряд опережает AWS по объему выручки (и вдумчивым ответ на имеющийся в котором U-SQL является PartiQL). В самом деле:


  • если говорить о мультимодельных СУБД прежнего типа, основанных на реляционной модели, Amazon Aurora явно уступает Azure SQL Database, не имея поддержки графовой модели;
  • сравнить мультимодельные СУБД нового типа (подобные ArangoDB и OrientDB) не получится вовсе: никакого аналога Azure CosmosDB в составе AWS нет.

Итак, хочется, чтобы абстрактная модель данных PartiQL скорее стала конкретной: неким аналогом модели ARS из Azure CosmosDB, и в AWS появилось соответствующее хранилище. Пока же можно поиграться с альфа-версией эталонной реализации PartiQL на Kotlin.


Ссылки



Похожие новости


Седьмого августа вышел релиз седьмой версии флагманского RDF-хранилища Stardog. Написав адаптеры ко всему на свете, создатели теперь заявляют: «data location is almost always irrelevant».





P.S. Спасибо JBL за наводку на оригинальный пост в блоге AWS Open Source.

Комментарии (18)


  1. databoom
    20.08.2019 23:37

    при этом они ведут себя вполне «таблично»

    А можно поподробнее?


    1. nitrosbase Автор
      20.08.2019 23:49
      +1

      Смысл в том, что при проходе древовидной структуры мы как бы генерируем таблицу. Первый столбец — где были на первом шаге, второй — где на втором. Чем правее столбец, тем больше в нем уникальных значений. «Маршрут» — это такой rowset provider, как OPENXML в MS SQL Server. Потом эти таблички можно подджойнивать к чему-нибудь или друг к другу.


      Менее утрированное объяснение — разделы 3.3 и 5.3 спецификации.


  1. Oz_Alex
    21.08.2019 06:06

    Есть хороший перевод на Хабре про изобретение ещё одного языка запросов — habr.com/ru/post/422667


    1. nitrosbase Автор
      21.08.2019 10:55
      +2

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


      Согласен, что «мусорных языков запросов» действительно много. Но ограничиться одним SQL не выйдет, коль скоро есть модели данных, отличные от реляционной. Прелесть PartiQL как раз в том, что это более-менее естественное расширение SQL. Одному из авторов SQL даже понравилось.


      Половина статьи по ссылке про ORM, не про языки запросов. Я бы уклонился от обсуждения по существу, а развернул бы эту часть его рассуждений против другой, про языки запросов. Можно сказать, что разные language integrated queries как раз для тех, кому лень выучить даже язык запросов.


  1. Taragolis
    21.08.2019 11:25

    SQL/JSON Standard-2016, не ?


    1. nitrosbase Автор
      21.08.2019 12:30

      Нет. Там упор на функции по работе с JSON, а здесь работа с JSON интегрирована в язык. Вероятно, авторы подумали: язык-то декларативный когда-то был, может, хватит его функциями раздувать? За счёт этого иерархические данные стали сущностями.


      И поэтому здесь, например, оказалось возможным поддержать лишь совсем базовый JSONPath, а там поддерживаемые возможности JSONPath раздуты чуть ли не до имеющихся в XPath.


      1. nitrosbase Автор
        21.08.2019 13:32

        сущностями

        Имелось в виду «сущностями первого класса».


      1. Taragolis
        21.08.2019 13:42

        Там упор на функции по работе с JSON, а здесь работа с JSON интегрирована в язык

        Если разработчики подписываются под то, что реализовали функционал из SQL/JSON (частичный или полностью), тогда получается, что работа с JSON интегрирована в язык.


        И поэтому здесь, например, оказалось возможным поддержать лишь совсем базовый JSONPath, а там поддерживаемые возможности JSONPath раздуты чуть ли не до имеющихся в XPath

        JSONPath в отличии от XPath не стандартизирован, поэтому каждый делает свою реализацию. Кстати какого функционала не хватает в реализации JSONPath по SQL/JSON?
        Ну и в (спеке PartiQL) нет вообще информации по JSONPath


        Просто пока выглядит как "очередной язык, который хочет казаться SQL, но работает несколько иначе, поэтому вы будете думать почему привычное вам, перестало работать". Как всегда рассудит время


        1. win32nipuh
          21.08.2019 14:35

          У них даже заявлено, что он SQL-compatible (с каким именно стандартом — пока не ясно).


        1. nitrosbase Автор
          21.08.2019 16:30

          Если разработчики подписываются под то, что реализовали функционал из SQL/JSON (частичный или полностью), тогда получается, что работа с JSON интегрирована в язык.

          В первой части соответствующего change proposal создатели стандарты писали, что давайте делать все «using built-in functions». То есть существуют, значит, какие-то иные способы, и есть между этими способами некоторая разница.


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


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


          Ну и в (спеке PartiQL) нет вообще информации по JSONPath

          У них это называется path navigation, которая бывает всего видов: tuple navigation и array navigation. И примечание: «notice that consecutive tuple/array navigations… navigate deeply into complex value».


          Кстати какого функционала не хватает в реализации JSONPath по SQL/JSON?

          Пройдусь по двум пунктам из своего поста («вот что делает иерархически организованные данные практически сущностями первого класса в PartiQL»), от второго к первому:


          • я так и не понял, как в SQL/JSON получить список ключей, и лучше в привязке к значениям, а не просто значения.
          • эти селекторы не «созависимы». Например, насколько понимаю, при SELECT JSON_VALUE(T.J, '$.persons[*].name'), JSON_VALUE(T.J, '$.persons[*].surname'), мы получим декартово произведение множеств имен и фамилий. То есть утрачивается реляционность. Может, можно сделать что-то с помощью JSON_TABLE, но уж больно все громоздко, я не разбирался.

          поэтому вы будете думать почему привычное вам перестало работать

          Обещают, что при представлении в абстрактной модели PartiQL чисто реляционных данных все запросы из SQL-92 останутся работоспособными. В конце концов, для разбирательств есть формальная семантика PartiQL. В других «очередных языках» с этим хуже.


          1. Taragolis
            21.08.2019 19:43

            В первой части соответствующего change proposal создатели стандарты писали, что давайте делать все «using built-in functions».

            Как бы логично, типов много. Как бы отработал a.country если a имеет тип int или varchar или point


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

            Как то токсичненько


            У них это называется path navigation

            Yet another standard


            tuple navigation

            Cоздатели же знают, что называют кортежами в других языках? Почему интересно не object navigation ?


            я так и не понял, как в SQL/JSON получить список ключей, и лучше в привязке к значениям, а не просто значения.

            $.keyvalue()
            Правда зачем, это не понятно. Нужен бизнес смысл этого действия


            эти селекторы не «созависимы». Например, насколько понимаю, при SELECT JSON_VALUE(T.J, '$.persons[].name'), JSON_VALUE(T.J, '$.persons[].surname'), мы получим декартово произведение множеств имен и фамилий.

            Не правильно понимаете, в режиме lax получите NULL, в режиме strict получите ошибку.
            Хотите массив получить, тогда JSON_QUERY, хотите отношение сгенерировать JSON_TABLE


            запросы из SQL-92 останутся работоспособными.

            Немного черного юмора: "А также добавят обратную совместимость с Windows 3.1 и дистрибутивами на ядре Linux 0.0.1"


            Кстати интересно, как отработает по такому JSON:


            {"a": 1, "a": 2, "a": 3, "b": null}


  1. win32nipuh
    21.08.2019 12:03

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


    1. nitrosbase Автор
      21.08.2019 15:44

      Реального мира нет, он съеден софтом, а софт подъедается облаками. Но ОК, пусть приватные и гибридные облака тоже имеют кусок.


      Для тех, кого не съели, в оригинальной записи в блоге предлагается архитектурная картинка. Я бы сказал, что тут примерно как с GraphQL. Стандартный путь — сделать resolver, который работает с имеющимся хранилищем. Но некоторые хранилища начинают и сами понимать GraphQL (тот же Stardog, упомянутый в статье).


      Вот в Couchbase, например, уже поддержали SQL++, сейчас вроде раздумывают, реализовать ли PartiQL.


      Но что дальше?

      Цель этой статьи была в том, чтобы на примере AWS (в предположении, что там все делают правильно), ответить на следующие вопросы:


      1. Какие парадигмы интеграции данных нынче актуальны? С организационной точки зрения, так сказать. Ответ — NoETL, data fabric и пр.
      2. Как это реализуется технически? Ответ — виртуализация источников, универсализация языков.
      3. Что будет после этого (хоть и к этому еще не все пришли)? Ответ — похоже, мультимодельность.

      Ну а системы, делающие все «правильно», есть и в «реальном мире».


      1. win32nipuh
        21.08.2019 16:44
        +1

        Ок, спасибо. Хорошо, заявлено использование PartiQL для запросов в гибридные источники, например, пусть даже разные серверы баз: SQL Server, PostgreSQL, MariaDB. Интересно, как и где? Только в амазонской туче можно такое использовать? Т.е. где-то должен быть реальный интерпретатор и «опросщик» реальных источников.


        1. Taragolis
          21.08.2019 19:54

          Ну прямо сейчас можно поднять AWS EMR с Presto или тоже самое сделать с AWS EC2 или вообще поднять на своем железе и работать все это будет на SQL


          1. win32nipuh
            22.08.2019 10:45
            +1

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

            Как загрузить файли с данными понятно, но куда и как указывать серверы баз?


            1. nitrosbase Автор
              23.08.2019 01:44

              Прошу прощения за задержку с ответом. Нет, REPL CLI умеет только работать с данными в абстрактной модели PartiQL (которая тем самым становится не такой уж и абстрактной). Отображать в нее данные из внешних источников он не умеет.


              Если очень хочется попробовать, в Redshift Spectrum поддержка PartiQL более полная, чем в S3 Collect. Нужно создавать внешние таблицы как описано здесь.


              Еще, говорят, PartiQL поддерживается в Amazon QLDB, но тот в статусе превью.


              1. win32nipuh
                23.08.2019 11:04
                +2

                Ок, проясняется, что все сыро в реализации, но не в описании амазона.
                Я, кстати, задал вопрос и в их форуме, ответов пока(?) нет:
                community.partiql.org/t/how-to-recognize-different-data-sources-in-a-query/47

                Там есть тоже логичный вопрос по стандарту SQL:
                Why only being compatible to SQL:92 and not at least to SQL:2016?
                community.partiql.org/t/why-only-being-compatible-to-sql-92-and-not-at-least-to-sql-2016/45/2