Мартин клеппман
Проектирование высоконагруженных приложений

(Designing Data-Intensive Applications)

Глава 3. Хранение и извлечение данных


Транзакционная обработка или аналитика?
На заре обработки бизнес-данных запись в базу данных обычно
соответствовала бизнес операции (commercial transaction ): совершению продажи, размещению заказа у поставщика, выплате зарплаты сотруднику и т.д.. Но по мере распространения баз данных в областях, не связанных с обменом денег, термин транзакция (transaction) всё равно прижился, обозначая группу операций чтения и записи, образующих логическую единицу.
Транзакция не обязательно должна обладать свойствами ACID (atomicity, consistency, isolation, and durability). Обработка транзакций означает лишь предоставление клиентам возможности чтения и записи с малой задержкой — в отличие от заданий пакетной обработки (batch processing jobs), которые выполняются только периодически (например, раз в день). Мы обсудим свойства ACID в главе 7, а пакетную обработку — в главе 10.
Несмотря на то, что базы данных стали использоваться для хранения самых разных типов данных — записей в блогах, действий в играх, контактов в адресной книге и т.д. — основная схема доступа оставалась похожей на обработку бизнес-транзакций. Приложение обычно ищет небольшое количество записей по некоторому ключу, используя индекс. Записи
вставляются или обновляются на основе ввода данных пользователем. Поскольку эти приложения являются интерактивными, модель доступа стала известна как обработка транзакций в реальном времени (OLTP online transaction processing).
Однако базы данных также стали всё чаще использоваться для аналитики данных, которая имеет совершенно другие модели доступа. Обычно аналитический запрос должен просмотреть огромное количество записей, читая только несколько столбцов за один раз, и вычислить агрегированную статистику (такую как количество, сумму или среднее значение), а не просто вернуть необработанные данные пользователю. Например, если ваши данные представляют собой таблицу транзакций продаж, то аналитические запросы могут быть следующими:
  • Какова была общая выручка каждого из наших магазинов в январе?
  • Насколько больше бананов, чем обычно, мы продали во время нашей последней акции?
  • Детское питание какой марки чаще всего покупают вместе с подгузниками марки X?
Эти запросы часто пишутся бизнес-аналитиками и попадают в отчёты, которые помогают руководству компании лучше принимать решения (бизнес-аналитика). Для того чтобы отличить эту модель использования баз данных от обработки транзакций, её называют оперативной аналитической обработкой (OLAPonline1 analytical processing). Разница между OLTP и OLAP не всегда очевидна, но некоторые типичные отличия перечислены в таблице 3-1.
Сначала одни и те же базы данных использовались как для обработки транзакций, так и для аналитических запросов. SQL оказался довольно гибким в этом отношении: он хорошо работает как для запросов типа OLTP, так и для запросов типа OLAP. Тем не менее, в конце 1980-х — начале 1990-х годов наметилась тенденция к тому, что компании перестали использовать свои OLTP-системы для аналитических целей, а стали выполнять аналитику на отдельной базе данных. Эта отдельная база данных получила название хранилище данных (data warehouse).
Хранилище данных
Предприятие может иметь десятки различных систем обработки транзакций: системы, обеспечивающие работу веб-сайта для клиентов; контрольные точки кассовых систем в физических магазинах; системы, отслеживающие запасы на складах, планирующие маршруты для транспортных средств, обслуживающие поставщиков, управляющие сотрудниками и т. д. Каждая из этих систем сложна и требует команды людей для её обслуживания, поэтому в итоге системы работают в основном автономно друг от друга.
От этих OLTP-систем обычно ожидают высокой доступности и обработки транзакций с низкой задержкой, поскольку они часто критически важны для функционирования бизнеса. Поэтому администраторы баз данных тщательно оберегают свои базы данных OLTP. Они обычно неохотно разрешают бизнес-аналитикам выполнять специальные аналитические запросы к базе данных OLTP, поскольку эти запросы часто являются ресурсозатратными, сканирующими большие части набора данных, что может отрицательно сказаться на производительности параллельно выполняющихся транзакций.
Хранилище данных, напротив, представляет собой отдельную базу данных, к которой аналитики могут обращаться по своему усмотрению, не затрагивая OLTP-операции. Хранилище данных содержит копии данных всех различных OLTP-систем компании только для чтения. Данные извлекаются из баз данных OLTP (с помощью периодического дампа данных или непрерывного потока обновлений), преобразуются в удобную для анализа схему, очищаются, а затем загружаются в хранилище данных. Этот процесс получения данных в хранилище известен как Извлечение-Преобразование-Загрузка (ETLExtract-Transform-Load) и показан на рисунке 3-8.
Рисунок 3-8. Упрощенная схема ETL в хранилище данных
Хранилища данных сегодня существуют почти на всех крупных предприятиях, однако в малых компаниях их почти не используют. Возможно, это связано с тем, что в большинстве малых компаний не так много различных OLTP-систем, и они оперируют небольшим объёмом данных — таким, чтобы его можно было запросить в обычной базе данных SQL или даже проанализировать в электронной таблице. Крупной компании требуется больше усилий, чтобы сделать то, что довольно просто сделать в компании небольшой.
Большим преимуществом использования отдельного хранилища данных, а не запросов к OLTP-системам напрямую для аналитики, является то, что хранилище данных может быть оптимизировано для аналитических схем доступа. Оказалось, что алгоритмы индексирования, рассмотренные в первой половине этой главы, хорошо работают для обработки транзакций, но не очень хорошо отвечают на аналитические запросы. В оставшейся части этой главы мы рассмотрим подсистемы хранения данных, оптимизированные для аналитики.
Расхождение между базами данных OLTP и хранилищами данных
Модель данных в хранилище данных чаще всего реляционная, поскольку SQL обычно хорошо подходит для аналитических запросов. Существует множество графических инструментов анализа данных, которые генерируют SQL-запросы, визуализируют результаты и позволяют аналитикам исследовать данные (с помощью таких операций, как детализация, расслоение и расщепление (drill-down и slicing and dicing)).
На первый взгляд, хранилище данных и реляционная база данных OLTP выглядят одинаково, поскольку обе имеют интерфейс запросов SQL. Однако внутреннее устройство этих систем может выглядеть совершенно по-разному, поскольку они оптимизированы для совершенно разных моделей запросов. Многие поставщики баз данных сейчас сосредоточены на поддержке либо транзакционной обработки, либо аналитических рабочих нагрузок, но не обеих моделей сразу.
Некоторые базы данных, такие как Microsoft SQL Server и SAP HANA, поддерживают обработку транзакций и хранение данных в одном и том же программном продукте. Однако они всё больше превращаются в две отдельных системы для хранения данных и для запросов, доступ к которым осуществляется через общий интерфейс SQL.
Поставщики хранилищ данных, такие как Teradata, Vertica, SAP HANA и ParAccel, обычно продают свои системы по дорогим коммерческим лицензиям. Amazon RedShift — это хостинговая версия ParAccel. В последнее время появилось множество проектов SQL-on-Hadoop с открытым исходным кодом; они ещё сыроваты, но стремятся конкурировать с коммерческими системами хранения данных. К ним относятся Apache Hive, Spark SQL, Cloudera Impala, Facebook Presto, Apache Tajo и Apache Drill. Некоторые из них основаны на идеях Dremel от Google.

Звёзды и Снежинки: схемы для аналитики
Как было показано в главе 2, в сфере обработки транзакций используется
широкий спектр различных моделей данных в зависимости от потребностей приложения. С другой стороны, в аналитике разнообразие моделей данных гораздо меньше. Многие хранилища данных используются в виде шаблона, известного как Схема звезды (Star Schema) или как многомерное моделирование (dimensional modeling).
Пример схемы на рисунке 3-9 показывает хранилище данных, которое можно встретить в розничной торговле продуктами питания. В центре схемы находится так называемая таблица фактов fact table (в данном примере она называется fact_sales). Каждая строка таблицы фактов представляет событие, произошедшее в определённое время (здесь каждая строка представляет покупку продукта покупателем). Если бы мы анализировали посещаемость сайта, а не розничные продажи, каждая строка могла бы представлять собой просмотр страницы или клик пользователя.
Рисунок 3-9. Пример звездчатой схемы для
использования в хранилище данных
Обычно факты фиксируются как отдельные события, поскольку это позволяет максимально гибко анализировать их в дальнейшем. Однако это означает, что таблица фактов может стать очень большой. Крупные предприятия, такие как Apple, Walmart или eBay, могут иметь в своём хранилище данных десятки петабайт истории транзакций, большая часть которых находится в таблицах фактов.
Некоторые из столбцов таблицы фактов являются атрибутами, например, цена, по которой был продан продукт и стоимость его покупки у поставщика (что позволяет рассчитать маржу прибыли). Другие столбцы в таблице фактов являются внешними ссылками на другие таблицы, называемые таблицами измерений (dimension tables). Поскольку каждая строка таблицы фактов представляет собой событие, измерения представляют собой кто, что, где, когда,как и почему для каждого события.
Например, на рисунке 3-9 одним из измерений является проданный продукт. Каждая строка в таблице dim_product представляет один тип продукта, который продаётся, включая его единицу складского учета (SKU), описание, название бренда, категорию, содержание жира, размер упаковки и т.д. Каждая строка в таблице fact_sales использует внешний ключ для указания того, какой продукт был продан в данной конкретной транзакции. (Для простоты, если клиент покупает сразу несколько разных продуктов, они представлены в виде отдельных строк в таблице фактов).
Даже дата и время часто представляются с помощью размерных таблиц, поскольку это позволяет закодировать дополнительную информацию о датах (например, праздничных днях), чтобы запросы могли различать продажи в праздничные и будние дни.
Название «Схема звезды» происходит от того, что при визуализации межтабличных связей таблица фактов находится в центре, окруженная таблицами измерений, а связи с этими таблицами напоминают лучи звезды.
Одна из разновидностей этого шаблона известна как схема снежинки (snowflake), в которой измерения дополнительно разбиваются на субизмерения. Например, могут существовать отдельные таблицы для брендов и категорий продуктов, и каждая строка в таблице dim_product может содержать ссылки на бренд и категорию в качестве внешних ключей, а не хранить их в виде строк в таблице dim_product. Схема снежинки более нормализована, чем схема звезды, но «звезда» часто предпочтительнее, поскольку с ней проще работать аналитикам.
В типичном хранилище данных таблицы часто бывают очень широкими: таблицы фактов часто имеют более 100 столбцов, иногда несколько сотен. Таблицы измерений также могут быть очень широкими, поскольку они включают все метаданные, которые могут быть важны для анализа — например, таблица dim_store может содержать подробную информацию о том, какие услуги предлагаются в каждом магазине, есть ли в нём пекарня, площадь, дату открытия магазина, дату последнего ремонта, расстояние до ближайшего шоссе и т.д.
1Смысл понятия «online» в OLAP неясен; вероятно, оно относится к тому факту, что запросы делаются не только для заранее подготовленных отчетов, но и то, что аналитики используют OLAP-систему интерактивно.
Часть 4. Глава 3. Хранение и извлечение данных