One Size Fits All / «Одна система на все случаи жизни»: идея, чьё время пришло — и прошло

Майкл Стоунбрейкер (CSAIL MIT, StreamBase Systems) и Угур Четинтемель (Brown University, StreamBase Systems). Доклад на конференции ICDE 2005. DOI: 10.1109/ICDE.2005.1.

Аннотация

Последние 25 лет развития коммерческих СУБД можно описать одной формулой: «одна СУБД на все случаи жизни» (one size fits all). Она означает, что традиционную архитектуру СУБД — изначально спроектированную и оптимизированную для обработки бизнес-данных — стали применять во множестве приложений, ориентированных на работу с данными, хотя их характеристики и требования сильно различаются.

В этой статье мы утверждаем, что идея «одного решения для всех» больше не соответствует рынку баз данных. Коммерческий рынок разделится на множество независимых движков баз данных; некоторые из них, возможно, будет объединять общий парсер запросов. В подтверждение мы рассматриваем системы потоковой обработки и хранилища данных. Кроме того, мы кратко обсуждаем другие области, для которых традиционная архитектура подходит плохо, и призываем заново осмыслить нынешнее разделение системных служб между отдельными продуктами.

1. Введение

Исследовательские прототипы реляционных СУБД System R [10] и INGRES [27] появились в 1970-е годы. Оба проекта стремились предложить заказчикам более ценное решение для задач обработки бизнес-данных, где использовалась IMS. Поэтому обе системы проектировали прежде всего для оперативной обработки транзакций (online transaction processing, OLTP). В 1980-е годы их коммерческие наследники — DB2 и INGRES соответственно — получили признание именно на этом рынке. Другие поставщики, в том числе Sybase, Oracle и Informix, следовали той же базовой модели: реляционные таблицы хранятся построчно, для индексации используются B-деревья, план запросов выбирает стоимостный оптимизатор, а транзакции обладают свойствами ACID.

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

Чтобы избежать этих проблем, все крупные поставщики СУБД делали ставку на один продукт. Мы утверждаем, что эта стратегия уже не сработала, а в будущем её несостоятельность станет ещё заметнее.

Статья устроена следующим образом. В разделе 2 на примере ключевых особенностей рынка хранилищ данных мы покажем, почему стратегия единой кодовой базы уже дала сбой. В разделе 3 рассмотрим потоковые приложения и конкретный случай, когда специализированный движок превосходит реляционную СУБД по производительности на два порядка. В разделе 4 разберём причины этого разрыва и объясним, почему традиционным СУБД, вероятно, не удастся стать конкурентоспособными на этом рынке. Поэтому мы ожидаем, что специализированные движки потоковой обработки займут на нём прочное место. В разделе 5 перечислим другие области, где универсальное решение вряд ли подойдёт, а специализированные системы баз данных могут оказаться жизнеспособными. Значит, рынок СУБД может заметно фрагментироваться. В разделе 6 обсудим, как системные службы разделены между продуктами, а в разделе 7 подведём итоги.

2. Хранилища данных

В начале 1990-х годов возникла новая тенденция: предприятия захотели собирать данные из нескольких операционных баз в единое хранилище для бизнес-аналитики. У крупной компании обычно около пятидесяти операционных систем, и у каждой есть пользователи, ожидающие быстрого отклика. Системные администраторы неохотно допускали — и по-прежнему допускают — аналитиков к тем же системам: сложные нерегламентированные запросы могут увеличить время отклика для операционных пользователей. Кроме того, аналитикам часто нужно видеть исторические тенденции и сопоставлять данные из разных операционных баз. Их требования заметно отличаются от требований пользователей транзакционных систем.

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

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

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

Схема звезда: центральная таблица фактов и таблицы измерений
Рис. 1. Типичная схема «звезда»

Помимо неё хранилище содержит таблицы измерений: сведения о магазинах, покупателях, товарах и периодах времени. Таблица фактов хранит внешний ключ для каждого измерения, поэтому естественным образом получается схема «звезда». Такие схемы повсеместны в хранилищах и почти не встречаются в OLTP. Известно также, что для хранилищ хорошо подходят bitmap-индексы, тогда как в OLTP предпочитают B-деревья. Причина проста: bitmap-индексы компактнее и быстрее на аналитической нагрузке, но плохо переносят частые транзакционные обновления. Поэтому многие поставщики поддерживают в одной СУБД оба вида индексов.

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

В первом приближении у большинства поставщиков фактически есть две СУБД: одна для хранилищ данных (bitmap-индексы, материализованные представления, схемы «звезда» и специальные приёмы оптимизации таких запросов), другая для OLTP (B-деревья и обычный стоимостный оптимизатор). Как показано на рисунке 2, объединяет их общий парсер запросов.

Общий парсер запросов и разные движки для OLTP и хранилища данных
Рис. 2. Архитектура современных СУБД

Общий интерфейс позволяет продавать такую конфигурацию как единую систему, хотя фактически поставщик предлагает несколько движков. Более того, и рынок OLTP, и рынок хранилищ требуют возможностей, бесполезных для другой стороны. Например, в OLTP-базе штат в почтовом адресе обычно хранится двухсимвольной строкой. Между тем пятьдесят штатов можно закодировать шестью битами. Если объём данных и число запросов оправдывают стоимость такого кодирования, компактное представление выгодно. Для хранилищ это обычно так, для OLTP — практически никогда. Значит, сложное кодирование полей полезно хранилищам и почти бесполезно транзакционным системам. Чем больше в продукте появляется функций для конкретного рынка, тем сильнее его архитектура напоминает схему на рисунке 2.

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

3. Потоковая обработка

В последние годы исследователи проявляют большой интерес к потоковым приложениям [7], [13], [14], [20]. Одна из причин — ожидаемая в ближайшие годы коммерческая жизнеспособность сенсорных сетей. Хотя больше всего внимания прессы досталось RFID, которая получит широкое распространение в розничной торговле и оптимизации цепочек поставок, существуют и другие технологии, например LoJack [3]. Многие отраслевые эксперты видят целое неосвоенное поле приложений мониторинга, которое откроется благодаря качественному сдвигу — появлению сетей из недорогих сенсорных устройств.

3.1 Новые приложения на основе сенсоров

У сенсорных сетей есть очевидные военные применения. Например, армия США изучает возможность снабдить каждого солдата датчиком жизненно важных показателей, чтобы эффективнее определять очерёдность медицинской помощи в бою. Во многих военных машинах уже есть GPS, но эти устройства пока не объединены в замкнутую систему управления. Военные хотели бы в реальном времени отслеживать все машины и замечать отклонения от маршрута. Датчик на орудийной башне вместе с координатами позволил бы обнаруживать ситуации перекрёстного огня, а датчик уровня топлива — лучше планировать дозаправку. В итоге армейское соединение из 30 000 человек и 12 000 машин вскоре может превратиться в крупную сенсорную сеть из нескольких сотен тысяч узлов, передающих сведения о состоянии и местоположении в реальном времени.

Вычислительные узлы сети и серверы дальнейшей обработки должны справляться с этим «пожарным шлангом» данных. Нужны сложные оповещения: например, командир взвода хочет узнать, когда три из четырёх его машин пересекут линию фронта. Нужны исторические запросы — «Где находилась машина № 12 последние два часа?» — и сквозные сводные запросы по всей системе, например: «Каково сейчас общее состояние боеготовности?»

Со временем сенсорный мониторинг появится и во многих гражданских областях. Один пример — наблюдение за пробками и предложение альтернативных маршрутов. Другой — динамическая плата за проезд, зависящая от загруженности дороги; именно эта идея вдохновила авторов теста Linear Road [9] для потоковых систем. В парках развлечений пассивные браслеты посетителей могут стать активными датчиками, чтобы оптимизировать загрузку аттракционов и находить потерявшихся детей. Мобильные телефоны уже являются активными устройствами, и нетрудно представить сервис, который найдёт для голодного владельца ближайший ресторан. Даже библиотечные книги получат метки: в большой библиотеке экземпляр, поставленный не на ту полку, можно потерять навсегда.

Распространено мнение, что традиционные СУБД плохо справятся с этим новым классом приложений мониторинга. В тесте Linear Road традиционные решения действительно оказались почти на порядок медленнее специализированного движка потоковой обработки [9]. На ограничения обычных СУБД указывает и опыт уже существующих потоковых приложений. Рассмотрим одно из них — обработку финансовых каналов данных.

3.2 Существующее приложение: обработка потоков финансовых данных

Большинство крупных финансовых организаций подписываются на информационные каналы, которые в реальном времени передают рыночные новости, сведения о заключённых сделках, цены спроса и предложения и так далее. Такие данные поставляют, например, Reuters, Bloomberg и Infodyne. Финансовые организации используют их в системах бизнес-аналитики в реальном времени, электронной торговли, контроля соответствия сделок внутренним правилам и требованиям Комиссии по ценным бумагам и биржам США (SEC), а также расчёта рисков в реальном времени, включая подверженность колебаниям валютных курсов. Подобные системы почти всегда разрабатывают самостоятельно: готовые программные продукты редко удовлетворяют специалистов предметной области.

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

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

Всего отслеживалось 4500 ценных бумаг. Для 500 наиболее активно торгуемых бумаг новая котировка считалась запоздавшей, если с момента предыдущей котировки той же бумаги прошло больше пяти секунд. Для остальных 4000, менее активных, порог составлял 60 секунд.

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

Наконец, задержки требовалось подсчитывать и по каждой из двух бирж — скажем, NYSE и NASD, — независимо от поставщика канала. После сотой задержки по каждой бирже система должна была выдать ещё по одному специальному сообщению. Итого нужны были четыре счётчика, каждый до ста, и отдельный сигнал при достижении порога. Абстрактная схема запросов показана на рисунке 3.

Потоки, фильтры и счётчики приложения Feed Alarm
Рис. 3. Приложение Feed Alarm в StreamBase

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

4. Обсуждение производительности

Приложение из предыдущего раздела реализовали в движке потоковой обработки (stream processing engine, SPE) StreamBase [5] — коммерческой, готовой к промышленной эксплуатации версии Aurora [8], [13]. На компьютере с процессором Pentium 2,8 ГГц, 512 Мбайт памяти и одним SCSI-диском схема с рисунка 3 обрабатывала 160 000 сообщений в секунду до насыщения процессора. Реализацию того же приложения на популярной коммерческой реляционной СУБД инженеры StreamBase смогли разогнать лишь до 900 сообщений в секунду.

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

4.1 «Входящая» и «исходящая» обработка

В основу традиционной СУБД заложена модель, которую авторы называют «исходящей» (outbound) обработкой и иллюстрируют на рисунке 4. Сначала данные помещают в базу (шаг 1). После индексации и фиксации транзакции они становятся доступны для запросов (шаг 2), а затем результат показывают пользователю (шаг 3). Эта модель «сначала сохранить, потом обработать» естественна: главная задача СУБД — принять данные и больше их не потерять.

Исходящая обработка: сначала хранение данных, затем запрос
Рис. 4. «Исходящая» обработка

В приложениях реального времени обязательная запись перед обработкой заметно увеличивает и задержку, и стоимость обработки каждого сообщения. Альтернативная модель без этого узкого места показана на рисунке 5. Входные потоки поступают в систему (шаг 1) и обрабатываются «на лету» в памяти сетью запросов (шаг 2), после чего результаты передаются клиентским приложениям (шаг 3). Обращение к постоянному хранилищу необязательно и во многих случаях может выполняться асинхронно. Отказ от обязательной записи снижает стоимость и задержку, заметно повышая производительность. Такую модель авторы называют «входящей» (inbound); именно её использует StreamBase.

Входящая обработка: сообщения проходят через сохранённые запросы
Рис. 5. «Входящая» обработка

Возникает естественный вопрос: «Не может ли СУБД выполнять входящую обработку?» Изначально СУБД создавались как исходящие движки, а триггеры появились в них гораздо позже как надстройка. У триггеров много ограничений, например на их число для одной таблицы, и нет способа гарантировать безопасность всей системы триггеров — в частности, отсутствие бесконечного цикла. Средства разработки обычно очень ограничены или вовсе отсутствуют: нет средств, позволяющих увидеть все задействованные в приложении триггеры, а добавить триггер к таблице через графический интерфейс нельзя. Для обычных таблиц существуют виртуальные и материализованные представления, для триггеров — нет. Наконец, триггеры часто работают медленно. В Feed Alarm инженеры StreamBase и с их помощью не смогли превысить 900 сообщений в секунду. Иными словами, триггеры остались поздней надстройкой и компонентом второго сорта.

Таким образом, реляционная СУБД — исходящий движок, к которому добавили ограниченную входящую обработку. Aurora и StreamBase, напротив, изначально являются входящими движками. Их устройство принципиально иное. Исходящий движок работает по модели pull: получает запрос и извлекает из хранилища нужные записи. Входящий движок работает по модели push: проводит поступающие сообщения через предусмотренные приложением этапы обработки.

То же различие можно сформулировать иначе. Исходящий движок хранит данные и выполняет над ними запросы. Входящий движок хранит запросы и пропускает через них поступающие данные — сообщения.

Теоретически можно создать движок, способный работать в обоих режимах, но это отдельная исследовательская задача. Пока же СУБД оптимизированы для исходящей обработки, а потоковые системы — для входящей. В Feed Alarm это различие подходов объясняет значительную часть наблюдаемого разрыва в производительности.

4.2 Правильные примитивы

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

SELECT AVG(salary)
FROM employee
GROUP BY department;

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

Поэтому потоковые движки дополняют SQL — или другой язык агрегирования — понятием окна. В StreamBase границы окна можно задавать по времени системных часов, по числу сообщений или по изменению другого атрибута. В Feed Alarm крайний левый блок каждого потока на рисунке 3 как раз является агрегатором. Он группирует данные по биржевому символу и для каждой бумаги создаёт окна из пар тиков: 1 и 2, 2 и 3, 3 и 4 и так далее. Такие скользящие окна часто нужны приложениям реального времени.

Агрегаторы StreamBase умеют учитывать опоздавшие, пришедшие не по порядку и потерянные сообщения. Для окон предусмотрены два дополнительных параметра. Тайм-аут заставляет закрыть окно и выдать результат, даже если обычное условие закрытия не выполнено; так система справляется с запаздывающими и пропавшими кортежами. Параметр slack, напротив, на некоторое время оставляет окно открытым уже после выполнения условия закрытия, чтобы принять сообщения, нарушившие порядок. Вместе эти параметры позволяют явно задать реакцию на аномалии входного потока и повысить устойчивость приложения.

В Feed Alarm каждое окно содержит два тика, а тайм-аут равен 5 или 60 секундам. Если интервал между соседними тиками превышает выбранный предел, окно закрывается. Таким образом, тщательно настроенная логика агрегирования попутно и очень дёшево обнаруживает задержку данных. Следующий блок отбрасывает нормальные результаты и пропускает только сообщения о тайм-ауте; оставшаяся часть приложения ведёт их учёт.

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

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

4.3 Бесшовная интеграция СУБД и логики приложения

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

Feed Alarm, напротив, представляет собой встроенную систему. Её целиком создаёт один разработчик или одна доверенная команда. Приложение объединяет три вида функций: обработку в стиле СУБД — например, агрегацию и фильтрацию; управляющую логику, направляющую сообщение на следующий этап; и собственно прикладную логику. В StreamBase их можно свободно чередовать. Прикладной код помещается в пользовательские блоки; в нашем примере это Count 100 на рисунке 6. Четыре строки C++ ведут счёт до ста и выставляют флаг, обеспечивающий выдачу нужных сообщений. Несколько предикатов и выходных дуг блока фильтра реализуют управляющую конструкцию if-then-else наряду с обычной фильтрацией потока.

Псевдокод пользовательского блока Count 100
Рис. 6. Логика Count 100

Итак, Feed Alarm сочетает обработку в стиле СУБД, условные выражения и функции на обычном языке программирования. StreamBase выполняет всё это в одном адресном пространстве, без переключений процессов. Подобную бесшовную интеграцию логики СУБД и традиционного программирования много лет назад предлагали Rigel [23] и Pascal-R [25], но коммерческие реляционные системы её не реализовали. Вместо этого появились хранимые процедуры с гораздо более ограниченной моделью программирования, а позднее — более мощные объектно-реляционные расширения, которые всё равно не обеспечили гибкой управляющей логики.

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

В Feed Alarm не показан ещё один аспект интеграции — хранение состояния. Большинству потоковых приложений нужно сохранять от нескольких мегабайт до нескольких гигабайт данных. Это могут быть справочники — например, перечень интересующих бумаг; таблицы соответствий, если разные каналы обозначают одну бумагу разными символами; и исторические сведения, например число запоздавших тиков за каждый день прошлого года. Иными словами, большинству потоковых приложений требуется табличное хранилище.

Для хранения состояния StreamBase встраивает Berkeley DB [4]. Вызов Berkeley DB внутри адресного пространства StreamBase примерно на порядок быстрее обращения к ней в клиент-серверном режиме из другого процесса. Это ещё один аргумент в пользу совместного выполнения движка и приложения.

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

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

4.4 Высокая доступность

Многие потоковые приложения должны обладать высокой доступностью (high availability, HA) и работать круглосуточно. Обычные механизмы журналирования и восстановления СУБД [22] плохо подходят для потоковой среды: они создают несколько принципиальных проблем.

Во-первых, восстановление по журналу занимает от десятков секунд до нескольких минут, и всё это время приложение недоступно — для финансовых и других систем реального времени это неприемлемо. Во-вторых, во время сбоя входящие потоки нужно где-то буферизовать, иначе данные безвозвратно потеряются. В-третьих, СУБД восстанавливает только табличные данные и не знает о состоянии операторов обработки. Счётчики Feed Alarm, например, в таблицах не хранятся и после сбоя будут потеряны. Можно было бы принудительно сохранять состояние всех операторов в таблицах, но это существенно замедлило бы приложение.

Очевидная альтернатива — пара процессов в стиле Tandem [11]. При сбое приложение быстро переключается на резервную машину, обычно работающую в режиме горячего резерва, и продолжает работу после небольшой паузы. Такой подход устраняет расходы на журналирование; в частности, StreamBase отключает ведение журнала в Berkeley DB.

Традиционным системам обработки данных для корректности часто нужно точное восстановление, но многим потоковым приложениям достаточно более слабых гарантий. Если мониторинг получает периодически обновляемые значения, короткий сбой и потеря нескольких сообщений могут быть допустимы. Потеря пары тиков при переключении Feed Alarm, вероятно, также не нарушит результат. В приложении, выдающем тревогу по сочетанию событий, потеря сообщения недопустима, зато временное дублирование может быть безвредно: монитор пациента способен пережить повтор «пульс 79», но не пропуск сообщения «пульс упал до нуля». Разумеется, некоторым системам всё же нужны строгие гарантии — например, управлению портфелем на основе каждой отдельной биржевой сделки.

Если достаточно более слабых гарантий корректности, можно использовать простые схемы переключения с малыми накладными расходами. Варианты обеспечения высокой доступности потоковых систем подробно рассмотрены в статье High-Availability Algorithms for Distributed Stream Processing [17].

4.5 Синхронизация

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

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

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

5. Одна система на все случаи жизни?

В предыдущем разделе мы перечислили архитектурные решения, из-за которых специализированный потоковый движок значительно быстрее традиционной СУБД. Разница затрагивает само внутреннее устройство систем: исполняющая подсистема StreamBase совсем не похожа на исполняющую подсистему обычной СУБД. Для целого класса приложений реального времени это даёт намного более высокую производительность. Если рынок окажется достаточно большим, потоковая обработка неизбежно получит отдельную кодовую базу.

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

5.1 Хранилища данных

Архитектурные различия между OLTP-системами и хранилищами данных, рассмотренные в разделе 2, — лишь верхушка айсберга. Со временем появятся и другие. Самое важное уже заметно: для аналитики данные выгоднее хранить по столбцам, а не по строкам.

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

Хранилищу данных, напротив, нужна оптимизация чтения: основную нагрузку создают нерегламентированные запросы к большим объёмам истории. Здесь гораздо эффективнее столбцовая модель, при которой значения одного атрибута для всех строк хранятся рядом. Её преимущества демонстрируют Sybase IQ [6], Addamark [1] и KDB [2].

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

5.2 Сенсорные сети

Запускать традиционную СУБД на узлах сенсорной сети непрактично [21], [24]. Такие сети исследуют для экологического и медицинского мониторинга, промышленной автоматизации, автономных групп роботов и умных домов [16], [19], [26], [28], [29].

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

Нужны гибкие и лёгкие абстракции баз данных, например TinyDB [18], оптимизированные для перемещения, а не долговременного хранения данных.

5.3 Текстовый поиск

Ни одна из современных на момент публикации поисковых систем не использовала СУБД как основное хранилище, хотя объёмы их данных были огромны и постоянно росли. Google, например, создала собственную систему хранения GFS [15], которая по причинам, сходным с рассмотренными в разделе 4, превосходила традиционные СУБД и файловые системы на своей целевой нагрузке.

Типичная нагрузка поисковой системы [12], [15] сочетает входящий поток от веб-краулеров — его нужно очистить и включить в индекс — с нерегламентированными поисковыми запросами к этому индексу. Запись в основном добавляет новые данные, чтение преимущественно последовательное, а для высокой производительности нужны одновременные добавления в один файл. Поскольку хранилище состоит из множества стандартных недорогих серверов, сбои являются нормой, а не исключением. Поэтому высокая доступность — одно из ключевых требований; обеспечить её можно только быстрым восстановлением и репликацией.

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

5.4 Научные базы данных

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

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

5.5 Базы XML-данных

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

6. О декомпозиции системных служб

Большинству потоковых приложений нужны три базовые службы:

В традиционной архитектуре эта логика распределена между тремя разнородными системами: (1) системой обмена сообщениями, например MQSeries, WebMethods или Tibco, которая обычно связывает компоненты по модели публикации и подписки; (2) СУБД, например DB2 или Oracle, которая долговременно хранит состояние; и (3) сервером приложений, например WebSphere или WebLogic, который предоставляет сервисы прикладным программам. Такая трёхзвенная конфигурация показана на рисунке 7.

Границы процессов в многоуровневой архитектуре потоковой обработки
Рис. 7. Многоуровневая архитектура потоковой обработки

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

Проследим путь одного сообщения. Шина принимает его и передаёт прикладному коду (шаг 1), который очищает и начинает обрабатывать данные. Если сообщение нужно сопоставить с историей или другим долговременным состоянием, приложение отправляет запрос серверу базы данных (шаги 2–3). Ответ возвращается тем же путём (шаги 4–5), после чего результат уходит в пользовательский интерфейс клиента (шаг 6). Одно сообщение шесть раз пересекает границы процессов. Помимо переключений процессов, адаптеры каждый раз преобразуют данные между внутренними форматами систем. Полезной работы получается мало по сравнению с накладными расходами; даже пакетная передача лишь смягчает проблему и продолжает ограничивать производительность.

Чтобы избежать этих потерь, потоковый движок должен объединить все три службы в одном компоненте — одном многопоточном процессе на каждой машине. Значит, в нём должны сочетаться элементы СУБД, сервера приложений и системы обмена сообщениями: специализированные возможности трёх типов программного обеспечения «под одной крышей».

Отсюда возникает вопрос: оптимально ли вообще привычное разделение системного ПО на серверы приложений, СУБД, ETL-системы, шины сообщений, файловые и веб-серверы? Эта декомпозиция сложилась отчасти исторически, отчасти из-за случайного стечения рыночных обстоятельств. Другие границы между продуктами не менее правдоподобны, поэтому определения компонентов и состав продуктов со временем могут заметно измениться.

7. Заключительные замечания

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

Литература
  1. Addamark Scalable Log Server. http://www.addamark.com/products/sls.htm.
  2. Kx Systems. http://www.kx.com/.
  3. LoJack.com, 2004. http://www.lojack.com/.
  4. Sleepycat Software. http://www.sleepycat.com/.
  5. StreamBase Inc. http://www.streambase.com/.
  6. Sybase IQ. http://www.sybase.com/products/databaseservers/sybaseiq.
  7. D. Abadi et al. Aurora: A Data Stream Management System (demo description). Proceedings of ACM SIGMOD, 2003.
  8. D. Abadi et al. Aurora: A New Model and Architecture for Data Stream Management. VLDB Journal, 2003.
  9. A. Arasu et al. Linear Road: A Benchmark for Stream Data Management Systems. Proceedings of VLDB, 2004.
  10. M. M. Astrahan et al. System R: A Relational Approach to Database Management. ACM Transactions on Database Systems, 1976.
  11. J. Bartlett, J. Gray, B. Horst. Fault Tolerance in Tandem Computer Systems. Tandem Computers Technical Report 86.2, 1986.
  12. E. Brewer. Combining Systems and Databases: A Search Engine Retrospective. Readings in Database Systems, 4th ed., 2004.
  13. D. Carney et al. Monitoring Streams: A New Class of Data Management Applications. Proceedings of VLDB, 2002.
  14. S. Chandrasekaran et al. TelegraphCQ: Continuous Dataflow Processing for an Uncertain World. Proceedings of CIDR, 2003.
  15. S. Ghemawat, H. Gobioff, S.-T. Leung. The Google File System. Proceedings of SOSP, 2003.
  16. T. He et al. An Energy-Efficient Surveillance System Using Wireless Sensor Networks. MobiSys, 2004.
  17. J.-H. Hwang et al. High-Availability Algorithms for Distributed Stream Processing. Proceedings of ICDE, 2004.
  18. S. Madden, M. Franklin, J. Hellerstein, W. Hong. The Design of an Acquisitional Query Processor for Sensor Networks. Proceedings of SIGMOD, 2003.
  19. D. Malan et al. CodeBlue: An Ad Hoc Sensor Network Infrastructure for Emergency Medical Care. WAMES, 2004.
  20. R. Motwani et al. Query Processing, Resource Management, and Approximation in a Data Stream Management System. Proceedings of CIDR, 2003.
  21. G. Pottie, W. Kaiser. Wireless Integrated Network Sensors. Communications of the ACM.
  22. K. Rothermel, C. Mohan. ARIES/NT: A Recovery Method Based on Write-Ahead Logging for Nested Transactions. Proceedings of VLDB, 1989.
  23. L. A. Rowe, K. A. Shoens. Data Abstraction, Views and Updates in RIGEL. Proceedings of ACM SIGMOD, 1979.
  24. P. Saffo. Sensors: The Next Wave of Information. Communications of the ACM.
  25. J. W. Schmidt. Some High-Level Language Constructs for Data of Type Relation. ACM Transactions on Database Systems, 2(3), 247–261, 1977.
  26. L. Schwiebert, S. Gupta, J. Weinmann. Research Challenges in Wireless Networks of Biomedical Sensors. MobiCom, 2001.
  27. M. Stonebraker, E. Wong, P. Kreps, G. Held. The Design and Implementation of INGRES. ACM Transactions on Database Systems, 1(3), 189–222, 1976.
  28. R. Szewczyk, J. Polastre, A. Mainwaring, D. Culler. Lessons from a Sensor Network Expedition. EWSN, 2004.
  29. T. Liu, P. Zhang, M. Martonosi. Implementing Software on Resource-Constrained Mobile Sensors: Experiences with Impala and ZebraNet. MobiSys, 2004.
Вверх