Родственные работы
Определяемые пользователями функции и процедуры – это давнишние средства СУБД, позволяющие расширять их функциональные возможности. Подобно тому, как определяемые пользователями типы (user-defined type, UDT) позволяют приспособить к потребностям пользователей то, что сохраняется в базе данных (см., например, [19]), определяемые пользователями функции дают возможность индивидуализировать то, как в системе баз данных обрабатываются данные [18, 11, 6, 20, 21, 22, 4, 12]. Оптимизации способов выполнения запросов к базе данных, содержащих вызовы UDF, посвящались серьезные исследования; см., например, [6, 11, 10]. Но большая этих работ выполнялась в контексте одного экземпляра базы данных, и в них почти не затрагивались аспекты параллельного выполнения UDF в параллельной СУБД без совместно используемых ресурсов.
Проводились некоторые исследования, посвященные определяемым пользователями агрегатам, скалярным функциям [14] и табличным операциям [15]. Традиционные определяемые пользователями агрегаты могут выполняться параллельно при наличии определяемых пользователями локальной и глобальной функций завершения вычислений (finalize function) [14]. Тогда частичные агрегаты вычисляются параллельно, а затем глобально завершается вычисление общего агрегата. Параллельные скалярные функции без состояния параллелизуются тривиально. Для другого класса скалярных функций, таких как "скользящее среднее" (moving average), требуется поддержка некоторого состояния, но если пользователь явно указывает способ разделения, то система может разделить данные и выполнить вычисление параллельно [14]. В качестве следующего шага в [15] предлагаются определяемые пользователями табличные операции, в которых, аналогично аргументам и результатам SQL/MR-функций, отношениями являются и аргументы, и результаты. При определении табличных операций пользователь должен статически предоставить системе стратегию разделения, чтобы сделать возможным параллелизм и проинформировать систему о том, как можно использовать соответствующую операцию.
При определении SQL/MR- функций явный или статический выбор способа разделения или использования функции не требуется – эта информация определяется во время обработки запроса на основе контекста использования SQL/MR-функции.
Идея табличной функции присутствует и в SQL, и определяемые пользователями табличные функции поддерживаются в большинстве комерческих СУБД (см., например, [12], [18], [16]). В Oracle и Microsoft SQL Server, кроме того, поддерживаются параметры-таблицы. Модель программирования, применяемая в этих системах по умолчанию, является не параллельной, так что функции пишутся в предположении, что они получат все входные данные. В некоторых реализациях допускается явная параллелизация функций. Например, у табличных операций в Oracle имеется раздел PARALLEL ENABLE, обрабатываемый во время создания функции и означающий, что параллелизация допускается, а также определяющий, каким образом входные строки следует разделять между параллельно выполняемыми потоками управления. В отличие от этого, в модели программирования для SQL/MR по умолчанию предполагается параллельное выполнение функций. Кроме того, в SQL/MR раздел PARTITION BY, определяющий способ группировки входных строк, является семантической частью запроса (а не опцией времени создания функции), так что для изменения способа группировки входных данных функцию переопределять не требуется.
В некоторых системах обеспечивается поддержка полиморфных (зависимых от контекта) результирующих схем функций. Этот подход является более гибким, чем традиционный подход к определению UDF, при котором схемы параметров и результата функции задаются во время ее создания. Например, в Oracle имеется родовой (generic) тип данных ANYDATASET, который можно использовать во время создания функции, чтобы отложить принятие решения о конкретном типе данных; во время обработки запроса функция должна будет указать системе, каков этот конкретный тип. Эта идея используется и в системе обработки данных компании Microsoft SCOPE [5], в частности, для поддержки извлечения структурированных данных из плоских файлов.
В SQL/MR- функциях этот подход полностью перенимается и расширяется; в них отсутствует потребность в конфигурировании во время создания, допускается полиморфизм входной схемы, а также допускается использование разделов специальных аргументов (подробности см. в разд. 3) функции, обрабатываемых во время выполнения запросов. Эти возможности индивидуализации времени выполнения запросов позволяют SQL/MR-функциям работать над различными входными данными; эти функции больше похожи на библиотечные функции общего назначения, а не на традиционные UDF.
В последнее время возрастает интерес к инфраструктурам распределенной параллельной обработки данных. К числу примеров относятся MapReduce компании Google [7], Dryad компании Microsoft [13], и проект с открытыми исходными текстами Hadoop [1]. Эти инфраструктуры обеспечивают мощные средства параллельной обработки данных, поскольку от пользователей требуется всего лишь реализация строго определенных процедурных методов. После этого инфраструктура управляет параллельным выполнением этих методов в крупных кластерах серверов. Основное преимущество таких систем состоит в том, что разработчикам требуется писать лишь простые процедурные методы, которые затем применяются параллельно с использованием строго определенной процедуры разделения и агрегации данных. Недостаток этих инфраструктур заключается в том, что разработчикам часто приходится писать код для выполнения задач, которые могут быть легко выражены на SQL или другом языке запросов. В частности, ограничивается повторное использование кода для непредвиденных запросов, поскольку отсутствует язык более высокого уровня, чем процедурный код.
Для MapReduce-подобных инфраструктур предлагались и системы более высокого уровня, включая Pig [17], Hive [2] и SCOPE [5]. Во всех них комбинировалась высокоуровневая, декларативная природа SQL с низкоуровневыми, процедурными, параллельными возможностями среды MapReduce. Хотя разработчики Hive и SCOPE пытаются добиться совместимости или хотя бы близости с SQL для его интеграции с кодом MapReduce, в этих системах предлагается значительно измененный синтаксис SQL.Например, в добавление к обычном разделу SELECT в SCOPE появляются разделы PROCESS, REDUCE и COMBINE. В отличие от этого, в SQL/MR вводится лишь небольшое число новых синтаксических конструкций и семантических правил, обеспечивающих использование вызовов параллельных функций в качестве таблиц. В целом эти языки являются хорошим развитием подхода MapReduce, поскольку в этой среде появляется некоторая разновидность декларативных языков. В подходе же SQL/MR возможности массивно-параллельной SQL-ориентированной СУБД расширяются на основе использования модели программирования MapReduce. Этот подход позволяет использовать в SQL/MR-функциях структуры данных, определяемые в реляционных базах данных на основе схем, и допускает применение оценочных оптимизиторов, в которых применяются реляционная алгебра и стастистика данных для перезаписи запросов.