8 августа 2014 года вышла новая версия HP Vertica 7.1. Команда Майкла Стоунбрейкера продолжает утверждать, что работа с большими данными сродни БАМу и продолжает новым версиям выдавать названия с строительной тематикой. Итак, Бульдозером (6 версия) по таблицам данные разровняли, сверху неструктурированными данными во Flex зону приложили (версия 7.0), пришла пора большого Экскаватора повернуть реки вспять. Встречаем версию Dragline 7.1! В этой статье я опишу, что же изменилось в новой версии.
Расширения функциональности проекций
Напомню для тех, кто в курсе и расскажу для тех, кто не знает: проекцией в Vertica называется материализация данных таблицы. Таблица в Vertica это описание структуры таблицы (столбцов), constraints и партиций. А непосредственно данные хранятся в проекциях, которые создаются на таблицы. Проекции чем-то похожи на индексы, они хранят данные по всем или не всем столбцам таблицы. Может быть более одной проекции на таблицу, проекции могут хранить отсегментированные и отсортированные данные по разным правилам. Данные во всех проекциях автоматически обновляются при обновлении записей таблицы. Фактически проекции содержат данные таблицы полностью всех колонок или частично определенных колонок. Жертвуется дисковое место серверов кластера, но значительно ускоряются выборки для разных групп запросов.
Выражения в проекциях
До новой версии в проекциях можно был указать исключительно только колонки таблицы. Это накладывало определенные ограничения на использование проекций. Например, если в запросах часто в фильтрации использовалось выражение по колонкам таблицы, поиск по этому фильтру не был максимально эффективным за счет того, что в проекции не было возможности указать сортировать хранимые данные по выражению. Сортировка же по столбцам выражения вряд ли помогла повысить производительность. Это могло вылиться в достаточно серьезную проблему. В качестве решения потребовалось бы добавить в таблицу новую колонку, в которую можно сохранять результат вычисления. Так же потребовалось изменить алгоритм загрузки в эту таблицу данных первоисточников, чтобы во время загрузки заполнять вычисляемый столбец. Так же пришлось бы перегружать всю таблицу, чтобы заполнить добавленное поле. Если в таблице десятки и сотни миллиардов записей и в нее идет постоянная загрузка, такое решение физически было бы невыполнимо.
В новой версии для проекций введена возможность указать как столбцы, так и выражения:
CREATE PROJECTION sales_proj (sale_id, sale_count, sale_price, sale_value) AS
SELECT sale_id, sale_count, sale_price, sale_count * sale_price
FROM sales
ORDER BY sale_count * sale_price
SEGMENTED BY HASH(sale_id) ALL NODES KSAFE 1;
Следующий запрос к созданной проекции таблицы:
SELECT *
FROM sales_proj_b0
WHERE value > 1000000
ORDER BY value;
при выполнении фактически моментально отдаст результат, используя сортировку выражения.
На такие проекции накладываются следующие ограничения:
- Нельзя использовать функции, которые могут изменить результат (например функцию TO_CHAR, так как она вернет разный результат в зависимости от выставленной кодировки клиента)
- Нельзя использовать служебные мета функции
- Нельзя обновлять записи таблицы оператором MERGE (UPDATE и DELETE разрешены)
Проекции такого типа можно создать и перестраивать на таблицу в любой момент времени, без остановки работы с ней пользователей и загрузки данных. Таким образом, проблема включения вычисляемого столбца в сортировку для повышения производительности запросов более не актуальна.
Top-K проекции
Это новый тип проекций в Vertica. Задача таких проекций максимально ускорить выполнение TOP запросов по фактам. Приведу простой пример, допустим нужно часто контролировать пять последних показаний счетчиков:
SELECT meter_id, reading_date, reading_value FROM (
SELECT meter_id, reading_date, reading_value, ROW_NUMBER()
OVER (PARTITION BY meter_id ORDER BY reading_date DESC) rn FROM readings) sq
WHERE rn <= 5;
Для таблицы с большим количеством записей запрос будет занимать ресурсы и время. Top-K проекции позволяют материализовать и хранить ТОП значений, переместив время вычисления ТОПов с момента выполнения запросов на момент добавления данных в таблицу:
CREATE PROJECTION readings_topk (meter_id, recent_date, recent_value) AS
SELECT meter_id, reading_date, reading_value
FROM readings
LIMIT 5 OVER (PARTITION BY meter_id ORDER BY reading_date DESC)
KSAFE 1;
Стоит отметить, что для упрощения получения ТОП значений данных в Vertica синтаксис SQL был специально расширен и запросы к данным можно теперь писать вот так:
SELECT meter_id, reading_date, reading_value
FROM readings LIMIT 5 OVER (PARTITION BY meter_id ORDER BY reading_date DESC);
Для быстрого обращения к ТОПам счетчиков теперь достаточно написать запрос к созданной проекции таблицы:
SELECT * FROM readings_topk;
Ограничением на данный тип проекций выступает запрет проводить изменение или удаление записей в таблицах, для которых существует такие проекции. Таким образом, этот тип проекций подходит только на таблицы, в которые всегда только добавляются данные (insert only).
При вставке новых записей в таблицу показаний счетчиков созданная проекция будет автоматически обновлять свои ТОП значения:
Живые агрегатные проекции
Тоже новый тип проекций. По аналогии с TOP-K проекциями, этот тип предназначен для материализации данных фактовых таблиц. Задачей данного типа проекций является ускорять простые агрегатные запросы, использующие агрегатные функции COUNT, MIN, MAX и SUM:
CREATE PROJECTION clicks_agg (user_id, page_id, click_date, num_clicks) AS
SELECT user_id, page_id, click_time::DATE click_date, COUNT(*) num_clicks
FROM clicks
GROUP BY user_id, page_id, click_time::DATE;
После создания и обновления этой проекции, в дальнейшем вместо выполнения таких агрегатных запросов на таблицу clicks, можно просто брать данных с проекции, вместо того, чтобы рассчитывать их каждый раз при выполнении запроса:
SELECT user_id, page_id, click_date, num_clicks
FROM clicks_agg;
Ограничением на данный тип проекций выступает запрет проводить изменения или удаления данных на таблицы, для которых были созданы такие проекции. Так же запрещается изменять наименование таблицы, ее колонок и их типов, которые они участвуют в живой агрегатной проекции.
P.S. Обратите внимание, на Top-K и живые агрегатные проекции нельзя при создании указывать сегментацию и сортировку. Они автоматически устанавливаются исходя из GROUP BY запроса проекции. Имеет роль перечисление полей в GROUP BY, так как оно используется для сортировки и сегментации проекции.
Перемещение партиций между таблицами
В идеальном хранилище данные в основном добавляются (факты) и иногда изменяются (измерения). Увы, идеальных хранилищ не бывает. Поэтому операции изменения фактов в хранилище данных достаточно частая и необходимая вещь. Архитектура Vertica ориентирована в первую очередь на сбор данных с множества источников в близком к реал-тайм времени и быстрому выполнению аналитических запросов на больших объемах данных. Для такой архитектуры, изменения и удаления разумных объемов записей для таблиц измерений вполне штатная и быстрая операция для Vertica. Однако, изменение огромного количества записей фактов для Vertica операция, которая может привести к снижению производительности всего кластера, особенно если будет производится часто и необдуманно. Оптимальным выходом здесь можно считать вариант, когда создается две таблицы. В одной таблице хранятся записи активного периода, в который как добавляются, так и изменяются записи. Во второй таблице хранятся записи закрытых периодов, которые уже не могут быть изменены. Такие таблицы затем объединяются в представлении посредством UNION ALL, которое далее используются конечными пользователями. В таком способе проблемой является сам момент закрытия периода, когда требуется перенести записи из активной в историческую таблицы. Делать это запросами INSERT/DELETE в рамках одной транзакции долго и не эффективно, если данных в закрываемом периоде очень много (сотни миллионов или миллиарды).
В Vertica 7.0.1 появилась функция MOVE_PARTITIONS_TO_TABLE, которая решает озвученную проблему:
SELECT MOVE_PARTITIONS_TO_TABLE ( 'fact_active', 2012, 2013, 'fact_history');
В этом примере переносятся партиции 2012 и 2013 годов из таблицы fact_active в таблицу fact_history. Выполняемая операция атомарная и для пользователей этих таблиц прозрачная. Если пользователь использует представление с UNION ALL на эти таблицы, то даже в момент выполнения запроса при работе данной функции он получит корректный результат. Операция переноса является мало-затратной, так как данные переносятся блоками на физическом уровне ROS контейнеров, а не логических записей.
В новой версии 7.1 появилась функция, которая позволяет поменять местами партиции между двумя таблицами:
SELECT SWAP_PARTITIONS_BETWEEN_TABLES( 'fact_active', 2012, 2013, 'fact_history');
В данном случае записи переносимых партиций таблицы fact_active перенесутся в таблицу fact_history, а записи партиций таблицы fact_history перенесутся в fact_active.
Расширение COPY
К существующей поддержке форматом сжатия BZIP и GZIP добавлен LZO.
Так же улучшена поддержка распределенной загрузки файлов командой COPY. В версии 6.1 уже была улучшена загрузка файлов путем распараллеливания загрузки файла на узле путем одновременной загрузки файла кусками. Теперь Vertica может распределять части загружаемого файла между несколькими узлами кластера, ускоряя загрузку слишком больших файлов.
Поддержка работы с вложенными массивами и вложенными картографическими данными во Flex таблицах
Достаточно важное расширение, так как работа с JSON структурами уже подразумевает частое использование вложенных массивов. Для решения задач такого круга в Vertica была расширена функциональность парсера загрузки данных из JSON в Flex таблицы и введен ряд функций, позволяющих на лету парсить вложенные массивы и картографические данные в форматах CSV и JSON.
Новые кодировки столбцов проекций
В 7 версии Vertica были добавлены новые типы столбцов long binary и long varchar, позволяющие хранить большие по размерам блобы. Эти столбцы никак не кодировались, хотя просилась возможность их сжатия для экономии дискового пространства и уменьшения дисковых операций. В новой версии для этого добавили типы кодировок BZIP_COMP и GZIP_COMP.
Активные резервные узлы
В новой версии Vertica добавлена возможность подключить к кластеру резервные узлы, которые подключены в кластери и работают, но не хранят данные и не производят никаких вычислений. В случае выпадения сервера из кластера и превышению предела времени его восстановления в кластере, Vertica автоматически переключает резервный узел в активный режим и замещает им сломанный сервер. Резервный сервер переносит на себя все данные, которые хранились на зеркале соседа сломавшегося узла и начинает полноценную работу в кластере. При необходимости администратор может явно указать заменить упавший сервер резервным, не дожидаясь, пока начнется его автоматическая замена. При выборе замещения сервера Vertica будет ориентироваться на описание Fail Group кластера. Если сервера распределены по группам (стойкам), то Vertica будет пытаться найти и запустить резервный сервер, находящийся в одной группе (стойке) с упавшим. Если подходящих серверов не будет найдено или же кластер не разбит по группам серверов, будет взят первый подходящий сервер. После возвращения упавшего сервера, администратор может переключить его обратно в работу кластера. В таком случае резервный сервер отдаст свои данные и перейдет снова в резервный режим ожидания.
Данная возможность позволяет упростить управление большим кластером, позволяя компаниям перестраховаться от потери производительности при возникающих проблемах с железом и снижая требования к постоянному контролю администраторов по работе кластера.
Поддержка REST API
Появилась возможность через https получать информацию с сервера Vertica по состоянию кластера, лицензии и управлять сервером и перехватывать события. Список функциональности фактически дублирует все, что реализовано в веб консоли Management Console и позволяет при необходимости встраивать управление и мониторинг сервера в собственные системы.
Динамическое перемещение выполняемых запросов между ресурсными пулами
Для тех, кто не в теме — ресурсный пул в Vertica это область ресурсов, имеющая свою память, параметры конкурентной работы и приоритеты. Каждый пользователь привязывается к определенному ресурсному пулу и его запросы выполняются в рамках его пула. Очень часто встречаются ситуации, когда пользователь является приоритетным, его запросы не являются «длинными», но должны выполнятся в максимально короткое время вне зависимости от общей загрузки кластера. В качестве примера можно привести операторов контактных центров (КЦ), у которых на телефоне висят пользователи с проблемами. Операторы должны в хранилище данных в максимально короткий срок получить информацию по работе этих пользователей. Здесь оптимальным является для операторов сделать собственный ресурсный пул с наивысшим приоритетом. Но что делать, если оператору понадобилось просмотреть по пользователю больше информации, чем планировалось? Например, он не смог определить истоки проблемы по информации текущего года и запросил данные прошлых лет. Такой запрос уже не будет «коротким», он займет большее время, оттянув на себя ресурсы пула и место в очереди выполнения, замедлив таким образом общую работу операторов КЦ. В предыдущих версиях Vertica единственным выходом было запрещать оператору выполнять запросы на такой большой объем данных и предлагать ему выполнить запрос под другим логином, который привязан к менее приоритетному и производительному пулу. Здесь уже понятно, что запросив столько данных, оператор и его клиент готовы ждать и моментальное выполнение запроса не ожидается.
В версии 7.1 эта проблема была решена с помощью возможности задать динамическое перемещение выполнения запроса в другой пул при превышении времени выполнения:
CREATE RESOURCE POOL userOverflow RUNTIMECAP '5 minutes';
CREATE RESOURCE POOL user RUNTIMECAP '1 minutes' CASCADE TO userOverflow;
CREATE USER "user1" RESOURCE POOL user;
В этом скрипте создаются два пула, запросы пользователя выполняются в пуле user, однако если они длиться более 1 минуты, то запрос перемещается для выполнения в пул userOverflow, в котором запросу разрешается выполнятся до 5 минут.
Для знающих английский, привожу блок схему работы запросов с пулами:
Обновление Management Console
Веб консоль HP Vertica наконец то была доработана до солидного уровня полноценной утилиты для администраторов. Теперь она позволяет проводить полноценный мониторинг и управление работой кластеров.
Значительно был переработан дизайн и повышено удобство интерфейса:
Появилась возможность отслеживать выполненные, выполняемые и ожидающие в очереди запросы:
Для запросов можно получить статистику их выполнения (профилирование), посмотреть план запроса или прервать работу.
Так же появилась возможность проводить мониторинг работы и администрировать ресурсные пулы, анализировать запросы для построения более оптимальных проекций на таблицы, проводить оценку работы Spread и контролировать общее состояние проекций таблиц в базе данных.
Расширение SQL
В агрегатные запросы добавлена поддержка ROLLUP, а также функции для работы с ROLLUP: GROUPING, GROUPING_ID и GROUP_ID.
Материализация WITH
Не смотря на то, что в Vertica есть временные таблицы, с помощью которых можно оптимизировать выполнение запросов, сохраняя в них промежуточные результаты, не всегда получается их использовать. Например, не каждый BI инструмент умеет поддерживать нюансы работы Vertica и во время работы сложные запросы разбивать на несколько с сохранением промежуточных результатов во временной таблице. Из того, что я знаю, это умеют делать Microstrategy и Tableau, однако вполне возможно, это умеет Oracle BI и другие инструменты BI. Для помощи в оптимизации работы сложных запросов с подзапросами, в Vertica введена поддержка автоматической материализации запросов, описанных в секции WITH для SELECT. Включение и выключение материализации выставляется администратором в опциях базы данных.
Следующий пример в обычном режиме работы дважды будет выполнять агрегатный запрос над одной таблицей:
WITH
revenue AS (
SELECT vendor_key, SUM(total_order_cost) AS total_revenue
FROM store.store_orders_fact
GROUP BY vendor_key ORDER BY 1)
-- End defining WITH clause statement
-- Begin main primary query
SELECT vendor_name,
vendor_address,
vendor_city,
total_revenue
FROM vendor_dimension v, revenue r
WHERE v.vendor_key = r.vendor_key AND total_revenue = (
SELECT MAX(total_revenue)
FROM revenue)
ORDER BY vendor_name;
Если включить опцию материализации WITH, то сервер Vertica автоматически создаст сессионную локальную временную таблицу, сохранит в нее результат запроса revenue из секции WITH и выполнит главный запрос, используя эту временную таблицу вместо подзапроса.
Хранение данных сервера на HDFS в Apache Hadoop
До текущего версии данные сервера могли хранится только на локальных дисках его серверов. Достаточно часто встречается ситуация, когда в хранилище находятся данные, которые обязательно нужно хранить, но которые достаточно редко используются пользователями. Не самое лучшее решение занимать такими данными дорогостоящее место на быстрых локальных дисках серверов.
Для этой цели в версии 7.1 ввели возможность хранить редко используемые данные в Apache Hadoop HDFS. Как и с другими дисками, появилась возможно зарегистрировать директорию HDFS как STORAGE и использовать ее для хранения ROS контейнеров, как полноценный дисковый массив. Есть несколько вариантов перемещения редко используемых данных на HDFS:
- Создать аналогичную таблицу с размещением на подключенном HDFS источнике и переносить в нее данные партиций с помощью функции MOVE_PARTITIONS_TO_TABLE
- Выставить для таблицы политику хранения данных с помощью функции SET_OBJECT_STORAGE_POLICY, для которой задать автоматический перенос записей на источник HDFS, если ключи партиций записей меньше заданного значения
Оптимизация работы HDFS коннектора
У загрузки данных из HDFS в Vertica ранее имелась проблема с производительностью при получения больших по размеру файлов. Сервер Vertica посылал запрос на чтение файла и если он был распределен между множеством серверов HDFS, то приходилось ожидать, пока он будет собран в единый файл, который потом забирался. Теперь Vertica умеет определять, что файл хранится в распределенном виде и самостоятельно подключатся к серверам, где он хранится, считывая и загружая параллельно все куски файла. Дополнительно коннектор теперь может контролировать скорость получения данных с узла HDFS и в случае падения скорости меньше заданного порога, автоматически переключатся на другой узел, пытаясь с него получить нужные данные с более высокой скоростью.
Полнотекстовые индексы
Впервые в Vertica появились индексы. Изначально архитектура Vertica проектировалась так, чтобы проекции могли более эффективно позволить работать с большими данными, чем это делали бы индексы. И это удалось. Однако прогресс не стоит на месте, появление в Vertica длинных строк (LONG VARCHAR) для хранения массивов текстов, привело к тому, что стал востребованным полнотекстовый поиск по таким полям. Проекция в данном случае является менее эффективным средством работы с текстами, чем полнотекстовые индексы. Помимо индексируемого текстового поля, индекс требует указания уникальных полей, по которому будет собираться возвращаться ключ записи, содержащей заданные в поиске слова. Например, есть таблица t_log, в которой есть уникальное PK поле ID, поле даты-времени записи в лог DATE и текстовое поле TEXT. Создание индекса на эту таблицу будет выглядеть так:
CREATE TEXT INDEX text_index ON t_log (id, text);
Поиск ID записей лога, в которых присутствует слово «WARNING» без учета регистра:
SELECT doc_id, word
FROM text_index
WHERE word = TxtIndex.Stemmer(LOWER('WARNING'));
Вывод все записей лога, в которых присутствует слово «WARNING» без учета регистра:
SELECT *
FROM t_log
WHERE id IN (
SELECT doc_id
FROM text_index
WHERE word = TxtIndex.Stemmer(LOWER('WARNING'))
);
Полнотекстовый поиск может учитывать при поиске похожие значения слов на искомое. Например, для вышеприведенных примеров индексом может быть возвращено слово «WARNINGS».
Поддержка Python 3
Добавлена поддержка Питона 3.3.4 под версию pyodbc 3.0.7
Расширения
Под Vertica отдельно выпущены пакеты расширений:
- HP Vertica Place — пакет работы с геоданными. Содержит множество функций, позволяющих работать с координатами, полигонами, рассчитывать дистанции и размеры объектов, вычислять площади перекрытия и т.д.
- HP Vertica Pulse — пакет для полноценного семантического анализа текстов. К сожалению, поддерживается только английский язык, поэтому для нашей страны этот пакет скорее всего не пригодится.
Резюме
Новая версия получила достаточно внушительный пакет изменений. Радует, что разработчики не зацикливаются на маркетинговых фишечках и чувствуется, что развитием продукта управляют сами клиенты, требованиях которых и формируют направление развития. Как архитектор компании EasyData по проектам работы с Vertica, могу сказать из личного опыта, что новая версия покрывает почти все пожелания наших проектов и наших клиентов. Так же чувствуется мощное движение по направлению дальнейшей интеграции с Hadoop, продолжение развития принципов нулевого администрирования на сверх больших кластерах серверов и непрерывную оптимизацию хранения и доступа к сверх большим данным. Отчетливо чувствуется дыхание Facebook, корректирующего развитие Vertica на своем кластере и объемах, не думаю, что в мире так много компаний, кого волновали бы вопросы управления тысячами серверов и петабайт данных. В любом случае нововведения очень полезны в наших текущих и будущих проектах, надеюсь Vertica не сбавит темпов и продолжит свое мощное непрерывное развитие учитывая задачи клиентов, а не в угоду маркетологам.
P.S. На текущий момент версия 7.1 доступна только клиентам Enterprise версии из my.vertica.com. Бесплатная Community версия выйдет чуть позже, когда Драглайн будет официально презентован 11 августа в Бостоне на ежегодной конференции HP. Фактически эта статья презентует эту версию для России раньше, чем это произойдет в Штатах. Я уверен, что мы заслужили первую презентацию на русском языке, показав лучшую динамику развития проектов на Vertica в нашей стране на фоне прочих стран мира.
Просьба сообщать мне найденные ошибки в тексте статьи и неточности в личку Хабра.
С уважением, Алексей.