Amazon представил PartiQL: SQL-совместимый язык запросов к данным в различных форматах

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


    Кадр из мультфильма «Трям! Здравствуйте!» (СССР, 1980)


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


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


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


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


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


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


    TL;DR

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


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


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


    Данные

    В абстрактной модели 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 в реляционных СУБД?


    Тогда попробуем кое-что посложнее. Допустим, значением 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 — возвращает ключи «в привязке» к значениям, то есть отношение в смысле реляционной модели.

    В принципе, это всё, что нужно знать о 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.

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

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

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

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

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

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

        +1

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


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

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

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


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


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

          +1

          SQL/JSON Standard-2016, не ?

            +1

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


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

              0
              сущностями

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

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

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


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

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


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

                  0
                  У них даже заявлено, что он SQL-compatible (с каким именно стандартом — пока не ясно).
                    0
                    Если разработчики подписываются под то, что реализовали функционал из 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. В других «очередных языках» с этим хуже.

                      0
                      В первой части соответствующего 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
                        Как бы отработал a.country если a имеет тип int или varchar или point

                        В PartiQL в свободном режиме (permissive mode) будет возвращено MISSING, в режиме проверки типов (type checking mode) запрос не выполнится. Можно «предохраняться»: CASE WHEN a IS TUPLE и т. д.


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

                        Ну да, ядовито. Но сами ведь пишут: а давайте сделаем как с XML.


                        Yet another standard

                        Точка и квадратные скобки, которые ведут себя практически как в Javascript, а вы там ниже предлагаете освоить JSON_TABLE, примеры использования которой ужасают даже в спецификации, где они по идее должны быть игрушечными :).


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

                        Создатели знают, что называется кортежем в SQL, и пытаются это обыграть. Кортеж из реляционной модели представляется в абстрактной модели данных PartiQL плоским (со скалярными значениями полей) объектом.


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

                        Спасибо, буду знать! Бизнес-смысл: допустим, есть внешний большой JSON и нужно по этим ключам сджойнить соответствующие значения из JSON с кортежами из таблицы, в которой в одном из полей лежит что-то похожее на эти ключи.


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

                        Насколько можно судить по таблицам в разделе 5.9.2 второй части,  правильно. Но даже рад, если неправильно. Значит, настолько все сложно :-) В то время как в PartiQL одна простая концепция (вместо мощного языка путей и впиливаемых в декларативный язык функций): маршрут порождает отношение. Добавил там в статье обновление, объясняющее, каким образом.


                        Кстати интересно, как отработает по такому JSON:
                        {"a": 1, "a": 2, "a": 3, "b": null}

                        В PartiQL в щадящем режиме [a] вернет, вероятнее всего, 1 (оставляется на откуп реализации). В режиме проверки типов будет ошибка, см. стр. 13 спецификации. Но можно вытащить и все значения "a" с помощью UNPIVOT.




                        Я бы предложил разойтись вот на чем. В SQL/JSON доступ к внешним JSON-данным отнесен к числу «non-goals» (см. раздел 1.1.8 первой части), в то время как в PartiQL все наоборот.
                        Во-вторых, SQL/JSON рассчитан на работу исключительно с JSON, в то время как PartiQL — и с другими иерархическими форматами (Parquet, Amazon Ion). Всем этим, можно считать, и обусловлена разница в дизайне SQL/JSON и PartiQL.

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

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


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


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


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

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


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

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

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

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

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

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

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


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


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

                            +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
                              0

                              Спасибо за ссылку. Да, реализация отстает, особенно в публично доступных сервисах. Мне-то больше интересна концепция, но, видимо, не смог её коротко и вместе с тем ясно изложить. Вынес ответ на первый комментарий в текст самой статьи.


                              А про «тучи», если интересно… Вот попался на днях гартнеровский прогноз:


                              • By 2023, 75% of all databases will be on a cloud platform, reducing the DBMS vendor landscape and increasing complexity for data governance and integration.
                              • By 2022, 50% of cloud buying decisions will be based on data assets provided by the cloud service provider rather than on product capabilities.

                  0

                  Вообще, появление PartiQL можно рассматривать в рамках тренда SQL Interfaces to Cloud Object Stores, зафиксированного в гартнеровских Hype Cycle for Data Management 2017, 2018 и 2019 годов и потихоньку смещающегося там вправо.


                  IBM движется тем же путем. Из Introducing IBM Cloud SQL Query от 2 апреля 2018 года:


                  SQL Query supports using standard ANSI SQL to analyze CSV, Parquet, and JSON files stored in IBM Cloud Object Storage.

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

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