Статьи

Эволюция языков баз данных: часть 3

В статье « Уровни абстракции нотаций, часть 1 » была представлена ​​концепция уровня абстракции, а в статье « Рождение нового поколения языков программирования? Часть 2 : «Я пытался применить его к эволюции языков программирования общего назначения. Однако эта структура применима и к предметно-ориентированным языкам. Давайте рассмотрим один из самых популярных доменов, где широко используются DSL: языки манипулирования данными.

Текущее состояние

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

Основные магазины

Классические базы данных ключ-значение, такие как Berkeley DB, обеспечивают простое сопоставление ключ-значение Языки запросов не поддерживаются. Наличие плоского пространства имен делает технологию принадлежащей к уровню 2. Более продвинутые структурированные базы данных значений ключей, такие как Cassandra, имеют языки запросов, которые могут рассматривать одну запись, соединения не поддерживаются изначально (но они могут быть реализованы с помощью инструментов, которые работать над Кассандрой, как Apache SparkSQL ). Таким образом, уровень этих баз данных можно классифицировать как 2.1.

Реляционные базы данных

Ранний SQL

В раннем SQL добавлена ​​ограниченная форма связей между таблицами и языками запросов, позволяющая использовать несколько таблиц в одном запросе с использованием объединений. Таким образом, «шаблоны» уровня 2 полностью реализованы в аспектах состояния и поведения. Это значительное улучшение по сравнению с хранилищами ключ-значение с точки зрения используемых абстракций.

Можно отметить, что конструкции уровня 2 (последовательности и плоские отображения из имен) используются повсеместно в SQL.

  • Структура базы данных / каталога / схемы / таблицы, где каждый уровень имеет вложенные элементы плоского пространства. Хотя это можно рассматривать как некоторую попытку иерархии, это не является действительно иерархической структурой пространства имен. Это можно сравнить с действительно иерархическими пространствами имен в Java или C #.
  • Все таблицы должны использоваться на одном уровне в одном предложении выбора для FROM. Использование подзапросов в предложении FROM было стандартизировано только в SQL 92 .
  • Таблица представляет собой последовательность строк, а строка представляет собой отображение имен на значения.

Практически единственным местом, где были поддержаны истинно иерархические конструкции, были выражения в предложениях where и select. Таким образом, это семейство языков может быть классифицировано как уровень 2.2.

Современный SQL

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

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

Учитывая эти особенности и ограничения, современный SQL можно классифицировать как уровень 2.3.

Сетевые базы данных

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

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

Граф Базы данных (текущее состояние)

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

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

Эти ограничения присутствуют во всех языках запросов графов, которые я проверял. Если есть исключение, я хотел бы узнать об этом. Эти ограничения позволяют нам классифицировать текущий пакет графовых баз данных как уровень 3.2.

Объектные базы данных также могут быть классифицированы как форма графовых баз данных. Язык OQL является хорошим языком запросов (однако все еще уровня 3.2) для графов, и мне лично он нравится больше, чем в других языках запросов для графов.

NoSQL против PreSQL и PostSQL

Классификация по уровням абстракции показывает, что не все базы данных NoSQL созданы равными. Хранение значения ключа может быть классифицировано как PreSQL или пре-реляционное. Графовые базы данных могут быть классифицированы как PostSQL или порт-реляционные. Альтернативные реализации реляционной модели, такие как языки баз данных на основе D, предлагают другой поверхностный синтаксис для практически тех же абстракций, что и в SQL. Я думаю, что NoSQL — это несколько запутанная терминология, так как она мало говорит о юзабилити технологии.

Следующее Малое Поколение

Как мы видели в предыдущем разделе, самый высокий из доступных языков баз данных — это уровень 3.2. Следующий подуровень 3.3 был бы в некотором смысле законченной технологией базы данных уровня 3. Попробуем сформулировать критерии для базы данных стадии 3.3 на основе опыта языка программирования общего назначения:

  1. (сделано) Явные ссылки
  2. (сделано) Рекурсивные структуры
  3. (сделано) Ссылки на конкретные виды
  4. (частичное) определение рекурсивного запроса (существует иерархическая декомпозиция, но обычно параметры не поддерживаются)
  5. (сделать) Введение концепции явного или неявного графа (объект, который владеет сущностями и отношениями и обеспечивает собственную область видимости и имеет собственное время жизни) и ациклические отношения между графами (объект графа может ссылаться на родительские графы, но не наоборот). Это также может быть использовано для организации лучшего аналога каталогов / схем РСУБД в графических базах данных.
  6. (сделать) Результаты рекурсивного / графического запроса (JPA EntityGraphs — ближайшая существующая вещь здесь, но она допускает только существующие сущности, а не произвольный граф объектов)
  7. (сделать) Рекурсивные / графические структуры в качестве параметров (включая наборы рекурсивных структур и неопределенной глубины структур)
  8. (сделать) Рекурсивные / графические результаты подзапроса (промежуточные результаты, повторно используемые в дальнейших запросах)

Чтобы понять разницу между запросами уровня 2.3 и запросами уровня 3.3, давайте рассмотрим запрос SQL, в котором подсчитываются элементы в категории, начиная с некоторой начальной категории.

WITH RECURSIVE rec_categories(id, name, parent_id) AS (
        SELECT id, name, parent_id FROM category 
         WHERE name = :name AND parent_id IS NULL
    UNION ALL
        SELECT c.id AS id, c.name AS name, c.parent_id AS parent_id 
          FROM category c, rec_categories r 
         WHERE c.parent_id = r.id
), item_counts AS (
    SELECT category_id, count(*) AS itemCount 
    FROM item GROUP BY category_id
)
SELECT r.id AS id, r.name AS name, r.parent_id AS parent_id,
       COALESCE(ic. itemCount, 0) AS itemCount
  FROM rec_categories r LEFT JOIN item_counts ic ON ic.category_id = r.id

Как видно, результатом является плоская структура. Параметр запроса «: name» передается неявно, он является глобальным для запроса и используется непосредственно в подзапросе.

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

def (categoryName : String) = {
def countItems(cat : Category) = #(
name: cat.name, 
itemCount: cat.items.count(), 
children: from child in cat.children select countItems(child)
); 
from cat in root.categories where cat.name = categoryName select countItems(cat)
}

Что можно увидеть здесь:

  • Рекурсия явная и следует графу данных
  • Возвращается рекурсивная структура данных, которая создается на лету
  • Параметры запроса являются явными
  • Подзапросы имеют параметры
  • Структура кода запроса соответствует структуре возвращаемого результата.

Для языков баз данных третьего поколения потребуется обновление API доступа к базам данных для поддержки иерархических результатов. Для JDBC нам понадобятся некоторые методы, такие как getResultSet (int pos ) или getResultSet (String name), чтобы перейти к результатам подструктуры , но конкретный драйвер базы данных может использовать getObject (…) в качестве аварийного выхода для этого до возможности поддерживается в стандарте. Большинство графовых баз данных уже имеют своего рода API обхода графов, и расширение этого API для поддержки результатов запросов выглядит естественным шагом.

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

Следующее главное поколение

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

  • Мета-структуры, мета-функции и мета-отношения (например, проверенные графы как библиотека и общие структуры, такие как «временные ряды»)
  • Черный ящик граф абстракция. Например, возможность хранить лямбда-выражения или экземпляры графического интерфейса в полях узла и использовать их в запросах. Возможность использовать их для формулирования запросов. Может возникнуть опасение, что черный ящик не разрешит гибкие запросы, но хороший черный ящик разрешит необходимые запросы и запретит плохие. Кроме того, никто не запрещает оптимизатору выбирать реальную реализацию (как это делают современные JIT-компиляторы).
  • Виртуальные графы (возможно изменяемые представления графов, материализованные или нет). Это просто еще один аспект предыдущего пункта. Абстракция по-настоящему черного ящика должна представлять собой граф, соответствующий некоторой схеме.
  • Точная сборка мусора, время жизни сущности благодаря достижимости от корней (необходимо для предыдущих элементов, поскольку ссылки становятся непредсказуемыми и, возможно, круглыми из-за абстракций черного ящика).
  • Общие ссылки на поля, типы и так далее. Возможность формулировать запросы, где некоторые другие отношения являются типизированным параметром.
  • (возможно) Динамические элементы хранения (очереди и темы событий, поддержка бизнес-процессов)

Как и в случае с языками программирования, мы, вероятно, увидим, что новые поколения баз данных работают медленнее, пока не будут разработаны эффективные методы оптимизации. Например, сборка мусора трудна в постоянном хранилище, и в облачном контексте, где мы сильно пострадали от CAP-теоремы, поэтому реализация облака может быть еще сложнее. Но через некоторое время методы оптимизации будут разработаны.

Если рассматривать этот вектор развития, мы могли бы видеть грядущие проблемы раньше. Например, уже можно было догадаться, что существует необходимость в сборке мусора для всей базы данных. Некоторые подходы, которые минимизируют IO, такие как генерация мусора в базе данных поколений, могут быть начаты в настоящее время как исследовательские проекты.

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

Объектно-реляционное отображение

Эта классификация позволяет нам получить некоторое представление об объектно-реляционных структурах отображения . Если мы рассматриваем инфраструктуру объектно-реляционного отображения как внутренний предметно-ориентированный язык, можно заметить, что они того же уровня абстракции, что и объектные базы данных и графовые базы данных.

Итак, инфраструктура объектно-реляционного отображения является реализацией языка уровня 3.2 над языком уровня 2.3.

С принятием языков баз данных графов можно ожидать, что несоответствие объектно-реляционного импеданса будет решено во многих аспектах, поскольку базы данных графов обеспечивают более прямое сопоставление. Тем не менее, языки программирования общего назначения теперь имеют уровень 4, а уровень 5 скоро появится. Таким образом, можно ожидать, что новое несоответствие импеданса приведет к несоответствию импеданса графов объектов, поскольку в языках разработки приложений возможны следующие функции, но они невозможны в графовых базах данных уровня 3:

  • Дженерики
  • Виртуальные графики
  • Вывоз мусора
  • Хранение элементов динамического поведения, реализация постоянного поведения (бизнес-процессы)

Это несоответствие может дать повод для нового поколения технологий сопоставления объектных баз данных. Даже когда это будет решено путем обновления технологий баз данных до уровня 4, мы можем ожидать следующего несоответствия импеданса и с развитием языков программирования общего назначения. Учитывая, что разработка языков программирования общего назначения несколько проще, чем разработка технологий баз данных, таких несоответствий трудно избежать.

Ортогональное измерение: сценарий распределения

Если мы рассмотрим эволюцию базы данных, это происходит в нескольких измерениях. Измерение, которое обсуждается в этой статье, является измерением уровней абстракции. Однако существуют и другие критические параметры, например, сценарии распространения. Если мы упорядочим по сложности реализации, мы получим следующие сценарии:

  1. Сериализация (текстовая или бинарная)
  2. внедренный
  3. Клиент-сервер
  4. Кластерный клиент-сервер
  5. Облако (высокое распределение, возможное разбиение, ненадежные и регулярно отказывающие узлы)

Каждый сценарий распространения радикально меняет методы реализации, потому что он меняет стоимость эксплуатации. И каждый следующий сценарий сложнее реализовать. Если мы рассмотрим эти сценарии распределения, принятие уровней абстракции для каждой модели происходит последовательно, и чем сложнее модель, тем более поздние уровни абстракции принимаются. Решение облачного хранения данных начиналось с решений класса сериализации (например, Google File System, предлагающей непрозрачную операцию чтения-записи), было принято только позднее хранилище значений ключей (Cassandra и другие). Теперь реляционные решения начинают появляться ( Apache Igniteи другие). С другой стороны, для модели сериализации уже реализована поддержка уровня 4, поскольку возможно сериализовать практически любой объект Java, включая обобщенные. Нереально ожидать, что новые уровни абстракции будут поддерживаться в облачном контексте немедленно, они, скорее всего, сначала будут приняты в меньшем масштабе, и они будут развиваться для поддержки более сложных моделей распределения.

Заключение

Языки, связанные с базой данных, были относительно «стабильными» в течение длительного времени. Как разработчик приложений, мне не нравится писать сложные запросы SQL, если они длиннее 10 строк. Написание 200+ строчных запросов — это, как правило, страшная история, которую нужно запомнить. По сравнению с этим, 200-строчный Java-метод или C-процедура не являются чем-то особенным, и их относительно легко контролировать и понимать с некоторой дисциплиной. И C, и Java позволяют дополнительно разложить его, чтобы уменьшить когнитивную нагрузку, если это трудно понять. Это демонстрирует огромный разрыв в удобстве использования языков. Я думаю, что это не является неотъемлемой чертой технологий баз данных и есть место для улучшений.

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

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