Результаты и обсуждение
Результаты загрузки для наборов данных в 535 мегабайт на узел и 1 терабайт на кластер показаны на рис. 1 и 2 соответственно. Для СУБД-X разделено время двух фаз загрузки, что показано на диаграммах в виде составного прямоугольника: нижняя часть представляет время выполнения параллельной команды LOAD, а верхняя соответствует процессу реорганизации.
Рис. 1. Время загрузки – набор данных задачи Grep (535 мегабайт на узел)
Рис. 2. Время загрузки – набор данных задачи Grep (1 терабайт на кластер)
На рис. 1 наиболее удивительна разница во времени загрузки данных в СУБД-X по сравнению с Hadoop и Vertica. Несмотря на параллельное выполнение команды LOAD в каждом узле кластера на первой фазе процесса загрузки, в действительности, данные в каждом узле загружались последовательно. Поэтому при возрастании общего объема данных пропорционально увеличивается и время загрузки. Это также объясняет то, что для набора данных в один терабайт на кластер время загрузки для СУБД-X не уменьшается при сокращении объема данных в расчете на узел. Однако выполнение сжатия и других служебных операций на данными в СУБД-X может производиться параллельно в нескольких узлах, и поэтому время выполнения второй фазы процесса загрузки сокращается вдвое при увеличении вдвое числа узлов, используемых для хранения терабайта данных. При отсутствии использования сжатия на уровне блоков или записей Hadoop явным образом превосходит и СУБД-X, и Vertica, поскольку в каждом узле происходит всего лишь копирование файла данных с локального диска в локальный экземпляр HDFS, а затем две его копии передаются в другие узлы кластера. Если бы данные загружались в Hadoop с использованием только одной копии каждого блока, то время загрузки уменьшилось бы втрое. Но, как будет показано в разд. 5, отсутствие нескольких копий часто приводит к увеличению времени выполнения заданий.
Производительность всех трех систем при выполнении этой задачи показана на рис. 4 и 5. Удивительно, что на этих рисунках не согласуются относительные различия между системами. На рис. 4 две параллельные системы баз данных показывают почти одинаковую производительность, более чем в два раза превосходящую производительность Hadoop. Но на рис. 5 и СУБД-X, и Hadoop работают более чем в два раза медленнее Vertica. Причина состоит в том, что в этих двух экспериментах использовались данные существенно разного объема. Результаты, показанные на рис. 4, были получены на данных очень малого объема (535 мегабайт на узел). Это приводит к тому, что не столь уж незначительные накладные расходы на запуск Hadoop становятся фактором, ограничивающим производительность системы. Как будет показано в п. 5.1.2, для запросов с небольшим временем выполнения (меньше одной минуты) время запуска доминирует в общем времени выполнения. По наблюдениям авторов, проходит 10-25 секунд, пока все задачи Map стартуют и начинают выполняться с полной скоростью в узлах кластера. Кроме того, по мере увеличения общего числа этих задач появляются дополнительные накладные расходы для координации активности узлов центральным контроллером заданий. Эти накладные расходы незначительно возрастают при добавлении узлов к кластеру и, как показывает рис. 5, при выполнении более протяженных задач обработки данных затмеваются временем, затрачиваемым на требуемую обработку.
На приведенных диаграммах верхняя часть прямоугольников Hadoop представляет время выполнения дополнительного задания MR, объединяющего выходные данные в один файл. Поскольку эта заключительная фаза выполнялась в виде отдельного задания MapReduce, в случае, показанном на рис. 4, на нее тратилась большая часть общего времени выполнения задачи, чем в случае с рис. 5, т.к. накладные расходы на запуск снова доминировали над полезными затратами, требуемыми для выполнения завершающей фазы. Хотя задача Grep является селективной, результаты, показанные на рис. 5, демонстрируют, что для выполнения этой объединительной фазы могут потребоваться сотни секунд из-за потребности в открытии и объединении большого числа мелких выводных файлов. Каждый экземпляр Map помещает свои выводные данные в отдельный файл HDFS, и поэтому, хотя каждый файл невелик, имеется много задач Map и, следовательно, много файлов в каждом узле.
На рис. 5, на котором показаны результаты экспериментов с набором данных в один терабайт на кластер, видно, что все системы при увеличении вдвое числа узлов выполняют задачу почти вдвое быстрее. Этого и следовало ожидать, поскольку в этих экспериментах общий объем данных, распределенных по узлам, остается неизменным. Hadoop и СУБД-X демонстрируют примерно одинаковую производительность, поскольку в этих экспериментах накладные расходы на запуск Hadoop амортизируются возросшим объемом обрабатываемых данных. Однако результаты отчетливо показывают превосходство Vertica над СУБД-X и Hadoop. Авторы объясняют это активным использованием в Vertica сжатия данных (см. п. 5.1.3), которое становится более эффективным при хранении в каждом узле большего объема данных.
Как уже говорилось по поводу задачи Grep, результаты этих экспериментов, показанные на рис. 6, снова демонстрируют, что параллельные СУБД значительно превосходят Hadoop на всех уровнях масштабирования кластера. Хотя относительная производительность всех систем деградирует при возрастании числа узлов и общего объема данных, на Hadoop это действует сильнее всего. Например, время выполнения в экспериментах с одним узлом и 10 узлами различается почти на 50%. Это опять объясняется возрастающими накладными расходами на запуск системы при добавлении узлов к кластеру. При выполнении быстро обрабатываемых запросов эти накладные расходы занимают значительную часть общего времени выполнения.
Еще одной важной причиной, по которой параллельные системы могут превосходить Hadoop, является то, что и в Vertica, и в СУБД-X используется индекс на столбце pageRank, и таблица Rankings сохраняется уже отсортированной по значениям pageRank. Поэтому выполнение этого запроса тривиально. Следует также заметить, что хотя у Vertica абсолютное время выполнения задачи остается небольшим, относительная производительность системы деградирует при увеличении числа узлов. И это несмотря на тот факт, что в каждом узле запрос продолжает выполняться одно и то же время (около 170 микросекунд). Но, поскольку узлы завершают выполнение запроса настолько быстро, система становится заполненной управляющими сообщениями, передаваемыми из слишком многих узлов, и обработка этих сообщений занимает большее время. В Vertica используется надежный механизм передачи сообщений для распределения запроса по узлам и обработки протокола фиксации , и этот механизм порождает значительные накладные расходы при использовании для обработки запросов более нескольких десятков узлов.
результаты экспериментов с задачей агрегации, представленные на рис. 7 и 8, снова показывают превосходство двух СУБД над Hadoop. СУБД выполняют эти запросы путем сканирования в каждом узле соответствующей локальной таблицы, извлечения значений полей sourceIP и adRevenue и выполнения локальной группировки. Затем эти локальные группы объединяются координатором запроса, который выводит результаты пользователю. Результаты на рис. 7 демонстрируют, что при большом числе групп две СУБД показывают примерно одинаковую производительность, поскольку значительная часть времени тратится на передачу большого числа локальных групп и их объединение координатором. В экспериментах с меньшим числом узлов Vertica работает немного лучше, поскольку в ней читается меньше данных (имеется прямой доступ к столбцам sourceIP и adRevenue), но при увеличении числа узлов система слегка замедляется.
Результаты на рис. 8 показывают, что поколоночную систему выгоднее использовать при обработке для решения данной задачи меньшего числа групп. Это объясняется тем, что значения двух требуемых столбцов (sourceIP и adRevenue) состоят всего из 20 байт, а весь кортеж таблицы UserVisits занимает более 200 байт. Поэтому при наличии относительно небольшого числа групп, которые требуется объединять, коммуникационные расходы существенно ниже, чем при выполнении первого варианта запроса. Таким образом, Vertica обгоняет по производительности две другие системы за счет того, что не читает неиспользуемые части кортежей UserVisits. Заметим, что время выполнения запроса на всех системах почти одно и тоже для любого числа узлов (с учетом того, что Vertica при росте числа узлов слегка замедляется). Поскольку в этой задаче требуется, чтобы система просматривала весь набор данных, время выполнения всегда определяется эффективностью последовательного сканирования и сетевыми накладными расходами каждого узла.
Производительность систем при выполнении этой задачи демонстрируется на рис. 9. Из-за ошибки в оптимизаторе запросов авторам пришлось немного изменить код SQL, использовавшийся в эксперименте со 100 узлами для Vertica. Из-за этого наблюдается такое значительное увеличение времени выполнения при переходе от 50 к ста узлам. Но даже при этом очевидно, что именно на этой задаче наблюдается наибольшее различие в производительности между Hadoop и двумя параллельными системами баз данных. Причина этого различия двояка.
Во-первых, несмотря на возросшую сложность запроса, производительность Hadoop по-прежнему ограничена скоростью, с которой может быть прочитана с диска крупная таблица UserVisits (20 гигабайт на узел). MR-программа вынуждена производить полное сканирование таблиц, в то время как параллельные системы баз данных могли успешно воспользоваться кластеризованным индексом на столбце UserVisits.visitDate для значительного сокращения объема данных, которые требовалось прочитать. Сравнивая временные расходы Hadoop на выполнение разных фаз программы, авторы обнаружили, что, независимо от числа узлов в кластере, на выполнение фаз 2 и 3 тратилось в среднем 24.3 и 12.7 секунды соответственно. В отличие от этого, на выполнение фазы 1, содержащей задачу Map, которая читает таблицы UserVisits и Rankings, в среднем тратилось 1434.7 секунды. Интересно, что примерно 600 секунд из этого времени было затрачено на примитивное чтение с диска таблиц UserVisits и Rankings, а 300 секунд – на разбиение, разбор и десериализацию различных атрибутов. Таким образом, накладные расходы ЦП, требуемые для разбора таблиц на лету, являются для Hadoop ограничивающим фактором.
Во-вторых, параллельные СУБД могут опираться на тот факт, что обе таблицы, UserVisits и Rankings, разделяются по столбцу соединения. Это означает, что обе системы могут производить соединение в каждом узле локально, без сетевых расходов на повторное разделение до выполнения соединения. Таким образом, им нужно просто выполнить в каждом узле локальную операцию хэш-соединения таблицы Rankings и отфильтрованной части таблицы UserVisits с последующим тривиальным выполнением раздела ORDER BY.
Результаты на рис. 10 показывают, что и у СУБД-X, и у Hadoop (не включая дополнительный процесс Reduce для объединения данных) для этой задачи обеспечивается почти константная производительность, поскольку в каждом узле хранится один и тот же объем данных Document, предназначенных для обработки, и этот объем данных остается константой (7 гигабайт) при добавлении узлов в проводившихся экспериментах. Как и ожидалось, дополнительная операция Hadoop по объединению данных работает все медленнее при добавлении узлов, поскольку объем выходных данных, которые должны обрабатываться одним узлом, увеличивается. Результаты для СУБД-X и Vertica на рис. 10 показаны в виде составных прямоугольников, в которых нижняя часть представляет время, затрачиваемое на выполнение UDF/парсера и загрузку данных в таблицу, а верхняя часть показывает время, затраченное на выполнение реального запроса. СУБД-X демонстрирует производительность хуже, чем у Hadoop, из-за дополнительных накладных расходов на покортежное взаимодействие между UDF и входным файлом, хранимым вне баз данных. Плохая производительность Vertica является следствием потребности в разборе данных вне СУБД и материализации промежуточных результатов на локальном диске до их загрузки в систему.