Классика баз данных - статьи

       

TeradataInputFormat


Основная идея нашего подхода заключается в том, что коннектор Teradata для Hadoop (TeradataInputFormat) посылает в Teradata EDW SQL-запрос Q, обеспечиваемый программой MapReduce, только один раз, и результаты сохраняются в некоторой PPI-таблице T (PPI – Partitioned Primary Index, разделенный первичный индекс). После этого каждый Mapper системы Hadoop посылает новый запрос Qi, в котором всего лишь в каждом AMP запрашивается i-ый раздел.

Обсудим теперь нашу реализацию более подробно. Прежде всего, класс TeradataInputFormat посылает в Teradata EDW следующий запрос P, основанный на запросе Q, который предоставляется программой MapReduce.

CREATE TABLE T AS (Q) WITH DATA PRIMARY INDEX ( c1 ) PARTITION BY (c2 MOD M) + 1 (P)

В этом запросе требуется, чтобы в Teradata EDW был выполнен запрос Q, и чтобы результаты были сохранены в новой PPI-таблице T. Хэш-значение столбца первичного индекса c1 каждой строки результата запроса определяет, в каком AMP должна храниться эта строка. После этого значение выражения, указанного в разделе Partition By, определяет физический раздел (местоположение) каждой строки в конкретном AMP. В одном AMP все строки с одним и тем же значением выражения Partition By физически хранятся совместно и могут быть напрямую и эффективно найдены Teradata EDW. Мы опустим детали того, каким образом мы автоматически выбираем столбец первичного индекса и выражение Partition By. После выполнения запроса Q и создания таблицы T в каждом AMP имеется M разделов с номерами от 1 до M (M – число Mapper'ов, запущенных в Hadoop). В качестве одного из дополнительных вариантов мы думаем разрешить опытным программистам самим задавать выражение Partition By через интерфейс TeradataInputFormat, чтобы получить более тонкое программное управление над тем, как следует разделять результаты запросов (конечно, это возможно, только если программистам хорошо известна демография данных).

Затем каждый Mapper посылает в Teradata EDW следующий запрос Qi (1 ≤ i ≤ M):


SELECT * FROM T WHERE PARTITION = i (Qi)

Teradata EDW напрямую параллельно определит местоположение всех строк i-го раздела каждого AMP и вернет эти строки i-му Mapper'у. Эта операция выполняется параллельно для всех Mapper'ов. После того как все Mapper'ы получат свои данные, таблица T удаляется.

Заметим, что если в исходном SQL-запросе всего лишь выбираются данные из базовой таблицы, которая является PPI-таблицей, то мы не создаем еще одну PPI-таблицу (T), поскольку можем непосредственно использовать существующие разделы для разделения данных, которые должен получить каждый Mapper.

В настоящее время у PPI-таблицы в Teradata EDW должен иметься столбец первичного индекса. Поэтому при вычислении запроса P системе Teradata EDW требуется разделить результаты запроса между всеми AMP в соответствии со значениями столбца первичного индекса. Одной из возможных в будущем оптимизаций является параллельное построение разделов результатов запроса в каждом AMP без перемещения результатов SQL-запроса Q между AMP. Еще одна возможная оптимизация состоит в том, что для построения M разделов нам в действительности не требуется сортировать строки в каком-либо AMP на основе значений выражения Partition By. Для наших целей мы может использовать здесь "номера псевдоразделов": первой 1/M-части строк результата запроса в любом AMP можно назначить номер раздела 1, ..., последней 1/M-части строк результата запроса в любом AMP можно назначить номер раздела M.

Заметим, что данные, выбираемые программой MapReduce через интерфейс TeradataInputFormat, не сохраняются в Hadoop после завершения программы MapReduce (если только их не сохранит сама программа MapReduce). Поэтому, если какие-то данные Teradata EDW часто используются многими программами MapReduce, более эффективно будет скопировать эти данные и материализовать их в Hadoop в виде файлов Hadoop DFS.

В зависимости от числа Mapper'ов, сложности SQL-запроса, предоставляемого программой MapReduce, и объема данных, затрагиваемых этим SQL-запросом, производительность подхода TeradataInputFormat, очевидным образом, может на порядки величин превышать производительность подхода DBInputFormat, что подтверждается предварительными результатами тестирования.



Подход TeradataInputFormat, описанный в этом подразделе, можно назвать подходом, основанным на горизонтальном разделении, в том смысле, что каждый Mapper выбирает часть результатов запроса из каждого AMP (узла). В настоящее время мы исследуем подход, основанный на вертикальном разделении, когда несколько Mapper'ов выбирают данные только из одного AMP при M > A (M – число Mapper'ов, запущенных Hadoop, и A – число AMP в Teradata EDW), или когда каждый Mapper выбирает данные из некоторого подмножества AMP при M < A, или когда каждый Mapper выбирает данные из одного и только одного AMP при M = A. Для реализации подхода, основанного на вертикальном разделении, в текущем варианте Teradata EDW требуется больше изменений, чем для реализации подхода, основанного на горизонтальном разделении. Мы предполагаем, что производительность любого из этих подходов не всегда будет превосходить производительность другого подхода.


Содержание раздела