Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Тарасов С. В. СУБД для программиста. Базы данных изнутри

.pdf
Скачиваний:
80
Добавлен:
29.11.2021
Размер:
4.08 Mб
Скачать

2.Непосредственная реализация функций агрегации над величинами (мерами).

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

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

5.Выражения фильтров записываются в близком к ORM стиле.

6.Фильтры уровня агрегации должны быть применены к результату map-reduce.

7.Восходящая сортировка кодируется единицей «1», нисходящая —

«1».

Данная иллюстрация хорошо показывает, чем декларативный язык 4 поколения SQL, отличается от императивного, основанного на языке 3 поколения типа Ява-скрипт.

Дляменяжеинтерпретацияданнойкартинкипредставилаинтерессовсем по другой причине: по замыслу авторов подобное переписывание запроса представляет собой более привычный и простой (!) для программиста код...

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

Ещё одну типичную ситуацию выпукло изобразили редакторы веб-сайта http://www.commitstrip.com. С их любезного разрешения ниже публикуется переведённая мной на русский язык история.

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

51

Рис. 9. Некомпетентность в SQL — не причина миграции на NoSQL.

52

Некомпетентность в SQL и реляционных СУБД не может служить серьёзным доводом в выборе NoSQL СУБД.

Многомерные модели данных

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

Рис. 10. Данные в ячейках гиперкуба трёхмерной модели

Гиперкуб по сути является многомерным разреженным массивом. Отличия от понятия массива, используемого в программировании незначительны:

индексы измерений поименованы: вместо целых чисел 1, 2,...N используется их заданное соответствие. Например, 1 — «Мука в/с», 2 — «Дрожжи», 3 — «Сахар» и т. д. — это обычная кодификация;

53

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

Последний пункт требует пояснений. Чтобы получить значение элемента N-мерного массива, необходимо задать индексы по всем измерениям. Следующее выражение возвращает сумму продаж муки клиенту «ООО Пирожки» в марте 2014 года.

Сумма := Сбыт[Индекс("2014-02"), Индекс("ООО Пирожки"), Индекс("Мука")];

что эквивалентно в нашем примере

Сумма := Сбыт[2, 2, 1];

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

Сумма := Сбыт[Индекс("2014-02"), Индекс("ООО Пирожки"), ?];

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

Сумма := Сбыт[Индекс("2014-02"), Индекс("ООО Пирожки"), Индекс("Мука")]; Сумма := Сбыт[?, Индекс("ООО Пирожки"), Индекс("Мука в/с")];

Сумма := Сбыт[?, Индекс("ООО Пирожки"), ?];

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

Microsoft OLAP.

Значение термина OLAP гораздо шире гиперкубов, поскольку сюда включены все методы интерактивной аналитической обработки данных: хранилища данных (data warehouse), так называемые витрины данных (data mart), добыча данных (data mining) и т. п. Часть перечисленных понятий может быть одновременно объектом пакетной обработки.

54

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

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

вставка, обновление и удаление записей приводит к пересчёту значений узлов и агрегатов, что резко увеличивает время и толщину транзакции.

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

Рис. 11. Реляционная схема хранения трёхмерного гиперкуба

55

Подобная реализация также имеет название ROLAP (Relational OLAP) и поддерживается большинством систем аналитической обработки.

В общем случае, число необходимых таблиц MTAB для хранения N- мерного гиперкуба определяется как сумма всех возможных сочетаний из N по k, где k меняется от 0 до N.

MTAB =

= 2N

В нашем примере при количестве измерений N=3 таблиц должно было быть 23=8, но для простоты исключена таблица с единственной строкой, не содержащая колонок-измерений. Соответствующую величину можно высчитать по наименее детализированной таблице (с одной колонкойизмерением).

Так как в общем случае для N измерений требуется 2N таблиц, их число растёт экспоненциально, поэтому на практике возможности ROLAP ограничиваются их небольшим (N < 10) количеством.

О применимости NoSQL

Как уже было сказано, NoSQL-решения и, в частности, основанные на ДОМ, имеют вполне конкретную область применения: первичный сбор и индексация информации, чью структуру мы не в состоянии классифицировать настолько полно, чтобы спроектировать соответствующую схему базы данных.

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

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

56

одного из таких решений приведён в главе «Неполно структурированные данные и высокая нагрузка» раздела о проектировании.

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

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

Приведём и другой тип труднореализуемой в рамках реляционной СУБД задачи. Пусть имеется множество однотипных объектов и связанных с каждым состояния, являющиеся длинным списком значений. Для простоты будем считать их двоичными: Состояние_1 = 0, Состояние_2 = 1, ...

Состояние_N = 0. ЧислоN можетбытьбольшим: сотниитысячисостояний.

Упрощённый пример этого типа задач из практики: объектом является пользователи, а в качестве состояний выступают их ответы на длинную анкету из вопросов «да/нет». Другой вариант — пользователи и признаки посещения/непосещения страницы веб-сайта; в этом варианте можно сэкономить на объёме и хранить только посещения. Ещё пример — дискретные состояния системы в виде показания датчиков на заданные моменты времени.

В рамках реляционной модели построить собственно структуру для хранения данных не представляет труда.

Приведённая схема напоминаетуже рассмотренную дляхранения модели САЗ. Отличие пока количественное: в САЗ мы оперируем сущностями с единицамиидесяткамиатрибутов, тогдакаквданномпримере— ссотнями и тысячами.

57

Рис. 12. Реляционная схема хранения множества бинарных состояний объекта

Количественное отличие быстро переходит в качественное, стоит лишь начать производить из БД простейшие выборки аналитического характера, например, «определить количество анкетированных, у которых ответ на Вопрос_1 - да, наВопрос_3 — нет, наВопрос_N — да ит.д». ЧислоN будет однозначноопределятьчислосоединенийвзапросе. Дляпростотысчитаем, что id_question соответствует его номеру.

SELECT COUNT(1) FROM

users u

INNER JOIN answers a1 ON u.id_user = a1.id_user AND a1.id_question = 1 AND a1.answer = 1

INNER JOIN answers a2 ON u.id_user = a2.id_user AND a2.id_question = 2 AND a2.answer = 0

...

INNER JOIN answers aN ON u.id_user = aN.id_user AND aN.id_question = N AND aN.answer = 1

58

Если N достаточно велико, то время выполнения такого запроса становится неприемлемым для интерактивной аналитической обработки, занимая долгие минуты. На практике, проблемы начинаются уже при N > 10..15, еслитаблицаответовсодержитдажедесяткимиллионовстрок13, а план выполнения запроса представляет собой скопление вложенных циклов со внутренними хеш-слияниями промежуточных выборок.

Рис. 13. План выполнения запроса в СУБД PostgreSQL при N = 15

Разумеется, средствами тонкой настройки и покупкой более мощной аппаратуры можно несколько увеличить производительность (более подробно об этом в следующих главах), но увеличив N добавлением ещё нескольких INNER JOIN мы, в лучшем случае, возвращаемся на исходные позиции.

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

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

59

производительность, но время выполнения становится предсказуемым, хотя в случае N > 20..30 может вновь стать неприемлемым.

SELECT COUNT(1) FROM

(SELECT id_user, COUNT(1) FROM answers

WHERE id_question = 1 AND answer = 1 OR id_question = 2 AND answer = 0

...

OR id_question = N AND answer = 1 GROUP BY id_user

HAVING COUNT(1) = N -- соответствует числу вопросов в запросе

) t

Соответствующий план будет примерно следующим, независимо от N.

Рис. 14. План выполнения запроса в СУБД PostgreSQL

При N порядка сотен, программист начинает сталкиваться с техническими ограничениями СУБД на число соединений в одном запросе и на общую длину текста запроса.

Как можно увидеть, даже в случае очень простых запросов проявляются трудности их реализации. Стоит несколько усложнить условия выборки, например «все пользователи, ответившие на вопросы NNN заданным образом, но по группе вопросов MMM совпадение не превышает 50%», как технические проблемы начинают расти в геометрической прогрессии.

Вариант решения с изменением начальной схемы путём денормализации и транспонирования таблицы ответов в структуру со многими колонками «Вопрос_1»,... «Вопрос_N» также не является возможным по техническим причинам: большинство реляционных СУБД имеет ограничения на число колонок в таблице или на общую длину строки (размер в байтах). Также будет невозможно построить индекс по всей совокупности колонок.

60