Основы Pig Latin
Правила
Здесь описаны соглашения по синтаксису и примерам кода в Справочнике по Pig Latin.
| Соглашение | Описание | Пример |
| ( ) | Скобки содержат один или несколько элементов. Скобки также используются для указания типа данных кортежа. | Несколько элементов: (1, abc, (2,4,6) ) |
| [ ] | Прямые скобки содержат один или несколько необязательных элементов. Прямые скобки также используются для указания типа данных отображения. В этом случае <> используется для обозначения необязательных элементов. | Необязательные элементы: [INNER | OUTER] |
| { } | Фигурные скобки содержат два или более элементов, один из которых является обязательным. Фигурные скобки также используются для указания типа данных множества. В этом случае <> используется для обозначения обязательных элементов. | Два элемента, один обязательный: { block | nested_block } |
| … | Горизонтальные многоточия указывают, что вы можете повторить часть кода. | Синтаксическое выражение Pig Latin: cat path [path …] |
| ВЕРХНИЙ РЕГИСТР нижний регистр | В общем случае, заглавные буквы указывают элементы, предоставляемые системой. В общем случае, строчные буквы указывают элементы, которые вы предоставляете. (Эти соглашения не строго соблюдаются во всех примерах.) | Выражение Pig Latin: a = LOAD 'data' AS (f1:int);
|
Зарезервированные ключевые слова
Здесь перечислены зарезервированные ключевые слова Pig.
| -- A | assert, and, any, all, arrange, as, asc, AVG |
| -- B | bag, BinStorage, by, bytearray, BIGINTEGER, BIGDECIMAL |
| -- C | cache, CASE, cat, cd, chararray, cogroup, CONCAT, copyFromLocal, copyToLocal, COUNT, cp, cross |
| -- D | datetime, %declare, %default, define, dense, desc, describe, DIFF, distinct, double, du, dump |
| -- E | e, E, eval, exec, explain |
| -- F | f, F, filter, flatten, float, foreach, full |
| -- G | generate, group |
| -- H | help |
| -- I | if, illustrate, import, inner, input, int, into, is |
| -- J | join |
| -- K | kill |
| -- L | l, L, left, limit, load, long, ls |
| -- M | map, matches, MAX, MIN, mkdir, mv |
| -- N | not, null |
| -- O | onschema, or, order, outer, output |
| -- P | parallel, pig, PigDump, PigStorage, pwd |
| -- Q | quit |
| -- R | register, returns, right, rm, rmf, rollup, run |
| -- S | sample, set, ship, SIZE, split, stderr, stdin, stdout, store, stream, SUM |
| -- T | TextLoader, TOKENIZE, through, tuple |
| -- U | union, using |
| -- V, W, X, Y, Z | void |
Чувствительность к регистру
Имена (псевдонимы) отношений и полей чувствительны к регистру. Имена функций Pig Latin чувствительны к регистру. Имена параметров (см. Замена параметров) и все другие ключевые слова Pig Latin (см. Зарезервированные ключевые слова) нечувствительны к регистру.
В примере ниже обратите внимание на следующее:
-
Имена (псевдонимы) отношений A, B и C чувствительны к регистру.
-
Имена (псевдонимы) полей f1, f2 и f3 чувствительны к регистру.
-
Имена функций PigStorage и COUNT чувствительны к регистру.
-
Ключевые слова LOAD, USING, AS, GROUP, BY, FOREACH, GENERATE и DUMP нечувствительны к регистру. Их также можно записать как load, using, as, group, by и т. д.
-
В операторе FOREACH к полю в отношении B обращаются с помощью позиционной нотации ($0).
grunt> A = LOAD 'data' USING PigStorage() AS (f1:int, f2:int, f3:int); grunt> B = GROUP A BY f1; grunt> C = FOREACH B GENERATE COUNT ($0); grunt> DUMP C;
Типы данных и многое другое
Идентификаторы
Идентификаторы включают в себя имена отношений (псевдонимы), полей, переменных и так далее. В Pig идентификаторы начинаются с буквы и могут быть продолжены любым количеством букв, цифр или символов нижнего подчеркивания.
Допустимые идентификаторы:
A A123 abc_123_BeX_
Недопустимые идентификаторы:
_A123 abc_$ A!B
Отношения, мешки, кортежи, поля
Выражения Pig Latin работают с отношениями. Отношение можно определить следующим образом:
-
Отношение — это мешок (точнее, внешний мешок).
-
Мешок — это коллекция кортежей.
-
Кортеж — это упорядоченное множество полей.
-
Поле — это фрагмент данных.
Отношение Pig — это мешок кортежей. Отношение Pig похоже на таблицу в реляционной базе данных, где кортежи в мешке соответствуют строкам в таблице. Однако, в отличие от реляционной таблицы, отношения Pig не требуют, чтобы каждый кортеж содержал одинаковое количество полей или чтобы поля в одинаковых позициях (столбцах) имели одинаковый тип.
Также обратите внимание, что отношения неупорядочены, что означает, что нет гарантии, что кортежи будут обрабатываться в определенном порядке. Кроме того, обработка может быть распараллелена, в этом случае кортежи не обрабатываются в соответствии с каким-либо полным упорядочением.
Обращение к отношениям
К отношениям обращаются по имени (или псевдониму). Имена назначаются вами как часть выражения Pig Latin. В этом примере имя (псевдоним) отношения — A.
A = LOAD 'student' USING PigStorage() AS (name:chararray, age:int, gpa:float); DUMP A; (John,18,4.0F) (Mary,19,3.8F) (Bill,20,3.9F) (Joe,18,3.8F)
Вы можете назначить псевдоним другому псевдониму. Новый псевдоним можно использовать вместо исходного псевдонима для ссылки на исходное отношение.
A = LOAD 'student' USING PigStorage() AS (name:chararray, age:int, gpa:float); B = A; DUMP B;
Обращение к полям
К полям обращаются с помощью позиционной нотации или по имени (псевдониму).
-
Позиционная нотация генерируется системой. Позиционная нотация обозначается знаком доллара ($) и начинается с нуля (0); например, $0, $1, $2.
-
Имена назначаются вами, используя схемы (или, в случае оператора GROUP и некоторых функций, системой). Вы можете использовать любое имя, которое не является ключевым словом Pig (см. Идентификаторы для примеров допустимых имён).
Учитывая отношение A выше, три поля выделены в этой таблице.
| Первое поле | Второе поле | Третье поле | |
| Тип данных | chararray | int | float |
| Позиционная нотация (генерируется системой) | $0 | $1 | $2 |
| Возможные имена (присвоенные вами с помощью схемы) | name | age | gpa |
| Значение поля (для первого кортежа) | John | 18 | 4.0 |
Как показано в этом примере, когда вы назначаете имена полям (используя предложение AS schema), вы по-прежнему можете ссылаться на поля с помощью позиционной нотации. Однако для отладки и удобства понимания лучше использовать имена полей.
A = LOAD 'student' USING PigStorage() AS (name:chararray, age:int, gpa:float); X = FOREACH A GENERATE name,$2; DUMP X; (John,4.0F) (Mary,3.8F) (Bill,3.9F) (Joe,3.8F)
В этом примере генерируется ошибка, потому что запрашиваемый столбец ($3) находится за пределами объявленной схемы (позиционная нотация начинается с $0). Обратите внимание, что ошибка обнаруживается до выполнения инструкций.
A = LOAD 'data' AS (f1:int,f2:int,f3:int);
B = FOREACH A GENERATE $3;
DUMP B;
2009-01-21 23:03:46,715 [main] ERROR org.apache.pig.tools.grunt.GruntParser - java.io.IOException:
Out of bound access. Trying to access non-existent : 3. Schema {f1: bytearray,f2: bytearray,f3: bytearray} has 3 column(s).
etc ...
Обращение к полям, являющимся сложными типами данных
Как отмечалось, поля в кортеже могут быть любого типа, включая сложные типы данных: мешки, кортежи и отображения.
-
Используйте схемы для сложных типов данных, чтобы именовать поля, которые являются сложными типами данных.
-
Используйте операторы разыменования для ссылки и работы с полями, которые являются сложными типами данных.
В этом примере файл данных содержит кортежи. Используется схема для сложных типов данных (в данном случае, кортежей) для загрузки данных. Затем операторы разыменования (точка в t1.t1a и t2.$0) используются для доступа к полям в кортежах. Обратите внимание, что когда вы назначаете имена полям, вы все еще можете ссылаться на эти поля с помощью позиционной нотации.
cat data; (3,8,9) (4,5,6) (1,4,7) (3,7,5) (2,5,8) (9,5,8) A = LOAD 'data' AS (t1:tuple(t1a:int, t1b:int,t1c:int),t2:tuple(t2a:int,t2b:int,t2c:int)); DUMP A; ((3,8,9),(4,5,6)) ((1,4,7),(3,7,5)) ((2,5,8),(9,5,8)) X = FOREACH A GENERATE t1.t1a,t2.$0; DUMP X; (3,4) (1,3) (2,9)
Типы данных
Простые и сложные
| Простые типы | Описание | Пример |
| int | Целое 32-битное со знаком | 10 |
| long | Целое 64-битное со знаком | Данные: 10L или 10l Вывод: 10L |
| float | 32-битное число с плавающей запятой | Данные: 10.5F или 10.5f или 10.5e2f или 10.5E2F Вывод: 10.5F или 1050.0F |
| double | 64-битное число с плавающей запятой | Данные: 10.5 или 10.5e2 или 10.5E2 Вывод: 10.5 или 1050.0 |
| chararray | Массив символов (строка) в формате Unicode UTF-8 | hello world |
| bytearray | Массив байтов (blob) | |
| boolean | булево | true/false (регистр не учитывается) |
| datetime | datetime | 1970-01-01T00:00:00.000+00:00 |
| biginteger | Java BigInteger | 200000000000 |
| bigdecimal | Java BigDecimal | 33.456783321323441233442 |
| Сложные типы | ||
| tuple | Упорядоченное множество полей. | (19,2) |
| bag | Коллекция кортежей. | {(19,2), (18,1)} |
| map | Набор пар ключ-значение. | [open#apache] |
Обратите внимание на следующие общие замечания о типах данных:
-
Используйте схемы для назначения типов полям. Если вы не присвоите типы, поля по умолчанию будут иметь тип bytearray, и неявные преобразования будут применяться к данным в зависимости от контекста, в котором используются эти данные. Например, в отношении B f1 преобразуется в целое число, потому что 5 — целое число. В отношении C f1 и f2 преобразуются в double, потому что мы не знаем тип ни f1, ни f2.
A = LOAD 'data' AS (f1,f2,f3); B = FOREACH A GENERATE f1 + 5; C = FOREACH A generate f1 + f2;
-
Если схема определена в качестве части оператора загрузки, функция загрузки попытается применить схему. Если данные не соответствуют схеме, загрузчик сгенерирует значение null или ошибку.
A = LOAD 'data' AS (name:chararray, age:int, gpa:float);
-
Если явное приведение типов не поддерживается, произойдет ошибка. Например, вы не можете привести chararray к типу int.
A = LOAD 'data' AS (name:chararray, age:int, gpa:float); B = FOREACH A GENERATE (int)name; This will cause an error …
-
Если Pig не может разрешить несовместимые типы с помощью неявных приведений, произойдет ошибка. Например, вы не можете складывать chararray и float (см. таблицу типов для сложения и вычитания).
A = LOAD 'data' AS (name:chararray, age:int, gpa:float); B = FOREACH A GENERATE name + gpa; This will cause an error …
У всех типов данных есть соответствующие схемы.
Кортеж
Кортеж — это упорядоченное множество полей.
Синтаксис
| ( поле [, поле …] ) |
Термины
| ( ) | Кортеж заключён в круглые скобки ( ). |
| поле | Фрагмент данных. Поле может быть любого типа данных (включая кортеж и мешок). |
Использование
Вы можете представить кортеж как строку с одним или несколькими полями, где каждое поле может быть любого типа, и любое поле может или не может иметь данные. Если поле не содержит данных, происходит следующее:
-
В операторе загрузки загрузчик вставит null в кортеж. Фактическое значение, которое подставляется вместо null, зависит от загрузчика; например, PigStorage подставляет пустое поле вместо null.
-
В операторе, отличном от загрузки, если запрашиваемое поле отсутствует в кортеже, Pig вставит null.
Также см. схемы кортежей.
Пример
В этом примере кортеж содержит три поля.
(John,18,4.0F)
Мешок
Мешок — это коллекция кортежей.
Синтаксис: Внутренний мешок
| { кортеж [, кортеж …] } |
Термины
| { } | Внутренний мешок заключен в фигурные скобки { }. |
| кортеж | Кортеж. |
Использование
Обратите внимание на следующее относительно мешков:
-
В мешке могут быть дублируемые кортежи.
-
В мешке могут быть кортежи с различным количеством полей. Однако, если Pig пытается получить доступ к полю, которого не существует, вместо него подставляется null.
-
В мешке могут быть кортежи с полями разных типов. Однако для эффективной обработки мешков схемы кортежей внутри этих мешков должны быть одинаковыми. Например, если половина кортежей включает поля chararray, а другая половина включает поля float, только половина кортежей примет участие в любом вычислении, поскольку поля chararray будут преобразованы в null.
Мешки имеют две формы: внешний мешок (или отношение) и внутренний мешок.
См. также схемы мешков.
Пример: Внешний мешок
В этом примере A — это отношение или мешок кортежей. Вы можете рассматривать этот мешок как внешний мешок.
A = LOAD 'data' as (f1:int, f2:int, f3:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3)
Пример: Внутренний мешок
Предположим, что мы группируем отношение A по первому полю, чтобы получить отношение X.
В этом примере X представляет отношение или мешок кортежей. Кортежи в отношении X имеют два поля. Первое поле имеет тип int. Второе поле имеет тип мешок; вы можете рассматривать этот мешок как внутренний мешок.
X = GROUP A BY f1;
DUMP X;
(1,{(1,2,3)})
(4,{(4,2,1),(4,3,3)})
(8,{(8,3,4)})
Карта
Карта — это набор пар ключ/значение.
Синтаксис (<> обозначает необязательное)
| [ key#value <, key#value …> ] |
Термины
| [ ] | Карты заключены в прямые квадратные скобки [ ]. |
| # | Пары ключ-значение разделяются символом решётки #. |
| key | Должен быть типом данных chararray. Должен быть уникальным значением. |
| value | Любой тип данных (по умолчанию bytearray). |
Использование
Значения ключей в отношении должны быть уникальными.
См. также схемы карт.
Пример
В этом примере карта содержит две пары ключ-значение.
[name#John,phone#5551212]
Значения NULL и Pig Latin
В Pig Latin значения NULL реализованы с использованием определения NULL в SQL как неизвестное или несуществующее. Значения NULL могут возникать естественным образом в данных или быть результатом операции.
Значения NULL, операторы и функции
Операторы и функции Pig Latin взаимодействуют со значениями NULL, как показано в этой таблице.
| Оператор | Взаимодействие |
| Операторы сравнения: ==, != >, < >=, <= | Если любое подвыражение равно NULL, результат равен NULL. |
| Оператор сравнения: matches | Если строка, с которой производится сравнение, или строка, определяющая соответствие, равна NULL, результат равен NULL. |
| Арифметические операторы: + , -, *, / % modulo ? : bincond CASE : case | Если любое подвыражение равно NULL, результат выражения равен NULL. |
| Оператор NULL: is null | Если проверяемое значение равно NULL, возвращает true; в противном случае возвращает false (см. Операторы NULL). |
| Оператор NULL: is not null | Если проверяемое значение не равно NULL, возвращает true; в противном случае возвращает false (см. Операторы NULL). |
| Операторы разыменования: кортеж (.) или карта (#) | Если разыменованный кортеж или карта равны NULL, возвращается NULL. |
| Операторы: COGROUP, GROUP, JOIN | Эти операторы обрабатывают значения NULL по-разному (см. примеры ниже). |
| Функция: COUNT_STAR | Эта функция подсчитывает все значения, включая значения NULL. |
| Оператор приведения типов | Приведение типа значения NULL из одного типа в другой приводит к значению NULL. |
| Функции: AVG, MIN, MAX, SUM, COUNT | Эти функции игнорируют значения NULL. |
| Функция: CONCAT | Если любое из подвыражений равно NULL, результат выражения равен NULL. |
| Функция: SIZE | Если проверяемый объект равен NULL, возвращается NULL. |
Для булевых подвыражений обратите внимание на результаты при использовании значений NULL с этими операторами:
-
Оператор FILTER — если выражение фильтра возвращает значение NULL, фильтр не пропускает эти значения (если X равен NULL, !X также равен NULL, и фильтр отвергнет оба).
-
Оператор Bincond — если булевое подвыражение возвращает значение NULL, результат выражения равен NULL (см. взаимодействия выше для арифметических операторов).
Значения NULL и константы
Значения NULL могут использоваться в качестве константных выражений вместо выражений любого типа.
В этом примере проецируются a и null.
A = LOAD 'data' AS (a, b, c). B = FOREACH A GENERATE a, null;
В этом примере внешнего соединения, если ключ соединения отсутствует в таблице, он заменяется на NULL.
A = LOAD 'student' AS (name: chararray, age: int, gpa: float); B = LOAD 'votertab10k' AS (name: chararray, age: int, registration: chararray, donation: float); C = COGROUP A BY name, B BY name; D = FOREACH C GENERATE FLATTEN((IsEmpty(A) ? null : A)), FLATTEN((IsEmpty(B) ? null : B));
Как и любое другое выражение, константы NULL можно неявно или явно привести к другому типу.
В этом примере и a, и null будут неявно приведены к типу double.
A = LOAD 'data' AS (a, b, c). B = FOREACH A GENERATE a + null;
В этом примере и a, и null будут приведены к типу int, a неявно, а null явно.
A = LOAD 'data' AS (a, b, c). B = FOREACH A GENERATE a + (int)null;
Операции, возвращающие NULL
Как уже отмечалось, значения NULL могут быть результатом операции. Эти операции могут возвращать значения NULL:
-
Деление на ноль
-
Возвращаемые значения пользовательских функций (UDF)
-
Разыменование поля, которого не существует.
-
Разыменование ключа, которого нет в карте. Например, в карте info, содержащей ['name'#'john', 'phone'#'5551212'], если пользователь пытается использовать info#address, возвращается NULL.
-
Доступ к полю, которого нет в кортеже.
Пример: Доступ к полю, которого нет в кортеже
В этом примере значения NULL вводятся, если поля не содержат данных.
cat data;
2 3
4
7 8 9
A = LOAD 'data' AS (f1:int,f2:int,f3:int)
DUMP A;
(,2,3)
(4,,)
(7,8,9)
B = FOREACH A GENERATE f1,f2;
DUMP B;
(,2)
(4,)
(7,8)
Значения NULL и функции загрузки
Как уже отмечалось, значения NULL могут естественным образом присутствовать в данных. Если значения NULL являются частью данных, функция загрузки должна правильно их обработать. Имейте в виду, что то, что считается значением NULL, зависит от функции загрузки; однако функция загрузки всегда должна сообщать значения NULL в Pig, генерируя значения Java null.
Функции загрузки Pig Latin (например, PigStorage и TextLoader) возвращают значения NULL, где данных нет. Например, пустые строки (chararrays) не загружаются; вместо этого они заменяются значениями NULL.
PigStorage — это функция загрузки по умолчанию для оператора LOAD. В этом примере используется оператор is not null для фильтрации имен с значениями NULL.
A = LOAD 'student' AS (name, age, gpa); B = FILTER A BY name is not null;
Значения NULL и операторы GROUP/COGROUP
При использовании оператора GROUP с одним отношением записи с ключом группы NULL группируются вместе.
A = load 'student' as (name:chararray, age:int, gpa:float);
dump A;
(joe,18,2.5)
(sam,,3.0)
(bob,,3.5)
X = group A by age;
dump X;
(18,{(joe,18,2.5)})
(,{(sam,,3.0),(bob,,3.5)})
При использовании операторов GROUP (COGROUP) с несколькими отношениями, записи с ключом группы NULL из разных отношений рассматриваются как разные и группируются отдельно. В примере ниже обратите внимание, что в выходных данных есть две записи, соответствующие ключу группы NULL: одна, содержащая кортежи из отношения A (но не отношения B), и одна, содержащая кортежи из отношения B (но не отношения A).
A = load 'student' as (name:chararray, age:int, gpa:float);
B = load 'student' as (name:chararray, age:int, gpa:float);
dump B;
(joe,18,2.5)
(sam,,3.0)
(bob,,3.5)
X = cogroup A by age, B by age;
dump X;
(18,{(joe,18,2.5)},{(joe,18,2.5)})
(,{(sam,,3.0),(bob,,3.5)},{})
(,{},{(sam,,3.0),(bob,,3.5)})
Значения NULL и оператор JOIN
Оператор JOIN — при выполнении внутренних соединений — следует стандарту SQL и игнорирует (фильтрует) значения NULL. (См. также Удаление значений NULL перед соединением.)
A = load 'student' as (name:chararray, age:int, gpa:float); B = load 'student' as (name:chararray, age:int, gpa:float); dump B; (joe,18,2.5) (sam,,3.0) (bob,,3.5) X = join A by age, B by age; dump X; (joe,18,2.5,joe,18,2.5)
Константы
Pig предоставляет константные представления для всех типов данных, кроме bytearrays.
| Пример константы | Примечания | |
| Простые типы данных | ||
| int | 19 | |
| long | 19L | |
| float | 19.2F или 1.92e2f | |
| double | 19.2 или 1.92e2 | |
| chararray | 'hello world' | |
| bytearray | Не применимо. | |
| boolean | true/false | Регистронезависимые. |
| Сложные типы данных | ||
| кортеж | (19, 2, 1) | Константа в этой форме создает кортеж. |
| мешок | { (19, 2), (1, 2) } | Константа в этой форме создает мешок. |
| карта | [ 'name' # 'John', 'ext' # 5555 ] | Константа в этой форме создает карту. |
Обратите внимание на следующее:
-
На системах UTF-8 вы можете указывать строковые константы, состоящие из печатаемых символов ASCII, такие как 'abc'; вы можете указывать управляющие символы, такие как '\t'; и вы можете указывать символ в Юникоде, начав его с '\u', например, '\u0001' представляет Ctrl-A в шестнадцатеричном формате (см. Википедию ASCII, Unicode и UTF-8). Теоретически, вы должны иметь возможность указывать константы, отличные от UTF-8, на системах, отличных от UTF-8, но, насколько нам известно, это не тестировалось.
-
Для указания константы long необходимо добавить l или L к числу (например, 12345678L). Если l или L не указаны, но число слишком велико, чтобы поместиться в int, проблема будет обнаружена во время разбора, и обработка будет прервана.
-
Любая числовая константа с десятичной точкой (например, 1.5) и/или экспонентой (например, 5e+1) рассматривается как double, если она не заканчивается на f или F, в этом случае ей назначается тип float (например, 1.5f).
-
Нет встроенного типа константы для поля datetime. Вы можете использовать udf ToDate со строковой константой chararray в качестве аргумента для создания значения datetime.
Определения типов данных для кортежей, мешков и карт применяются к константам:
-
Кортеж может содержать поля любого типа данных
-
Множество — это коллекция кортежей
-
Ключ карты должен быть chararray; значение карты может быть любого типа данных
Сложные константы (с значениями или без них) могут использоваться в тех же местах, где можно использовать скалярные константы; то есть, в операторах FILTER и GENERATE.
A = LOAD 'data' USING MyStorage() AS (T: tuple(name:chararray, age: int));
B = FILTER A BY T == ('john', 25);
D = FOREACH B GENERATE T.name, [25#5.6], {(1, 5, 18)};
Выражения
В Pig Latin выражения — это конструкции языка, используемые с операторами FILTER, FOREACH, GROUP и SPLIT, а также функциями eval.
Выражения записываются в общепринятой математической инфиксной нотации и адаптированы к набору символов UTF-8. В зависимости от контекста, выражения могут включать:
-
Любой тип данных Pig (простые и сложные типы данных)
-
Любой оператор Pig (арифметический, сравнения, null, булевый, ссылка, знак и приведение типа)
-
Любую встроенную функцию Pig.
-
Любую пользовательскую функцию (UDF), написанную на Java.
В Pig Latin
-
Арифметическое выражение может выглядеть так:
X = GROUP A BY f2*f3;
-
Строковое выражение может выглядеть так, где a и b — chararrays:
X = FOREACH A GENERATE CONCAT(a,b);
-
Булево выражение может выглядеть так:
X = FILTER A BY (f1==8) OR (NOT (f2+f3 > f1));
Выражения полей
Выражения полей представляют поле или оператор ссылка, применённый к полю.
Выражения со звёздочкой
Выражения со звёздочкой ( * ) могут использоваться для представления всех полей кортежа. Это эквивалентно явному перечислению полей. В следующем примере определения B и C идентичны, а MyUDF вызывается с одними и теми же аргументами в обоих случаях.
A = LOAD 'data' USING MyStorage() AS (name:chararray, age: int);
B = FOREACH A GENERATE *, MyUDF(name, age);
C = FOREACH A GENERATE name, age, MyUDF(*);
Типичная ошибка при использовании выражения со звёздочкой показана ниже. В данном примере программист хочет подсчитать количество элементов в множестве во втором поле: COUNT($1).
G = GROUP A BY $0;
C = FOREACH G GENERATE COUNT(*)
Существуют некоторые ограничения на использование выражения со звёздочкой, когда схема входных данных неизвестна (null):
- Для операторов GROUP/COGROUP нельзя включать выражение со звёздочкой в столбец GROUP BY.
- Для оператора ORDER BY, если у вас в столбце ORDER BY проект-звёздочка, то вы не можете иметь никаких других столбцов ORDER BY в этом операторе.
Выражения проекции диапазона
Выражения проекции диапазона ( .. ) могут использоваться для проекции диапазона столбцов из входных данных. Например:
- .. $x : проектирует столбцы с $0 до $x включительно
- $x .. : проектирует столбцы до конца, включительно
- $x .. $y : проектирует столбцы до $y включительно
Если у входного отношения есть схема, вы можете ссылаться на столбцы по имени, а не по позиции. Вы также можете комбинировать имена и позиции столбцов в выражении; например, «col1 .. $5» является допустимым.
Выражения проекции диапазона могут использоваться во всех случаях, когда разрешено выражение со звёздочкой (звёздочка).
Выражения проекции диапазона могут использоваться в следующих операторах: FOREACH, JOIN, GROUP, COGROUP и ORDER BY (также когда ORDER BY используется вложенном блоке FOREACH).
Несколько примеров показаны здесь:
.....
grunt> F = foreach IN generate (int)col0, col1 .. col3;
grunt> describe F;
F: {col0: int,col1: bytearray,col2: bytearray,col3: bytearray}
.....
.....
grunt> SORT = order IN by col2 .. col3, col0, col4 ..;
.....
.....
J = join IN1 by $0 .. $3, IN2 by $0 .. $3;
.....
.....
g = group l1 by b .. c;
.....
Существуют некоторые ограничения на использование формы выражения проекции диапазона «до конца» (например, «x ..»), когда схема входных данных неизвестна (null):
- Для GROUP/COGROUP форма выражения проекции диапазона «до конца» не допускается.
- Для ORDER BY форма выражения проекции диапазона «до конца» поддерживается только как последний столбец сортировки.
..... grunt> describe IN; Schema for IN unknown. /* This statement is supported */ SORT = order IN by $2 .. $3, $6 ..; /* This statement is NOT supported */ SORT = order IN by $2 .. $3, $6 ..; .....
Булевы выражения
Булевы выражения могут состоять из UDF, возвращающих булево значение, или булевых операторов (см. Булевы операторы).
Выражения кортежей
Выражения кортежей формируют подвыражения в кортежи. Выражение кортежа имеет вид (выражение [, выражение …]), где выражение — общее выражение. Самое простое выражение кортежа — выражение со звёздочкой, которое представляет все поля.
Общие выражения
Общие выражения могут состоять из UDF и почти любого оператора. Так как Pig не рассматривает булевый тип как базовый тип, результат общего выражения не может быть булевым. Выражения полей являются самыми простыми общими выражениями.
Схемы
Схемы позволяют назначать имена полям и объявлять типы полей. Схемы необязательны, но мы рекомендуем использовать их всякий раз, когда это возможно; объявление типов приводит к лучшей проверке ошибок на этапе анализа и более эффективному выполнению кода.
Схемы для простых типов и сложных типов могут использоваться там, где уместно определение схемы.
Схемы определяются операторами LOAD, STREAM и FOREACH с помощью ключевого слова AS. Если вы определяете схему с помощью оператора LOAD, то именно функция загрузки обеспечивает соответствие схеме (см. LOAD и Пользовательские функции для получения дополнительной информации).
Обработка известных схем
Обратите внимание на следующее:
- Вы можете определить схему, включающую как имя поля, так и тип поля.
- Вы можете определить схему, включающую только имя поля; в этом случае тип поля по умолчанию — bytearray.
- Вы можете не определять схему; в этом случае поле не имеет имени, а тип поля по умолчанию — bytearray.
Если вы назначаете имя полю, вы можете ссылаться на это поле по имени или по позиционному обозначению. Если вы не назначаете имя полю (поле не имеет имени), вы можете ссылаться на поле только по позиционному обозначению.
Если вы назначаете тип полю, вы можете впоследствии изменить тип с помощью операторов приведения типа. Если вы не назначаете тип полю, поле по умолчанию имеет тип bytearray; вы можете изменить тип по умолчанию с помощью операторов приведения типа.
Обработка неизвестных схем
Обратите внимание на следующее:
- При выполнении JOIN/COGROUP/CROSS нескольких отношений, если у любого отношения неизвестная схема (или отсутствует определённая схема, также известная как нулевая схема), схема результирующего отношения будет нулевой.
- Если вы применяете FLATTEN к множеству с пустой внутренней схемой, схема результирующего отношения будет нулевой.
- Если вы применяете UNION к двум отношениям с несовместимой схемой, схема результирующего отношения будет нулевой.
- Если схема нулевая, Pig рассматривает все поля как bytearray (в фоновом режиме Pig определит реальный тип полей динамически).
См. примеры ниже. Если тип данных поля не указан, Pig будет использовать bytearray для обозначения неизвестного типа. Если число полей неизвестно, Pig определит неизвестную схему.
/* The field data types are not specified ... */
a = load '1.txt' as (a0, b0);
a: {a0: bytearray,b0: bytearray}
/* The number of fields is not known ... */
a = load '1.txt';
a: Schema for a unknown
Как Pig обрабатывает схему
Как показано выше, за несколькими исключениями, Pig может определить схему отношения заранее. Вы можете проверить схему определённого отношения, используя DESCRIBE. Pig применяет эту вычисленную схему во время фактического выполнения, приводя входные данные к ожидаемому типу данных. Если процесс успешен, результаты возвращаются пользователю; в противном случае для каждой записи, не преобразованной в требуемый формат, генерируется предупреждение. Обратите внимание, что Pig не знает фактические типы полей во входных данных до выполнения; вместо этого Pig определяет типы данных и выполняет соответствующие преобразования на лету.
Наличие детерминированной схемы очень мощно; однако иногда это происходит за счёт производительности. Рассмотрим следующий пример:
A = load 'input' as (x, y, z); B = foreach A generate x+y;
Если вы выполните DESCRIBE для B, вы увидите один столбец типа double. Это происходит потому, что Pig выбирает самый безопасный вариант и использует наибольший числовой тип, когда схема неизвестна. На практике входные данные могут содержать целочисленные значения; однако Pig приведёт данные к типу double и гарантирует, что будет возвращён результат типа double.
Если схему отношения невозможно вывести, Pig просто использует текущие данные и распространит их через конвейер.
Схемы с операторами LOAD и STREAM
С операторами LOAD и STREAM схема, следующая за ключевым словом AS, должна быть заключена в скобки.
В этом примере оператор LOAD включает определение схемы для простых типов данных.
A = LOAD 'data' AS (f1:int, f2:int);
Схемы с оператором FOREACH
С операторами FOREACH схема, следующая за ключевым словом AS, должна быть заключена в скобки, когда используется оператор FLATTEN. В противном случае схема не должна быть заключена в скобки.
В этом примере оператор FOREACH включает FLATTEN и схему для простых типов данных.
X = FOREACH C GENERATE FLATTEN(B) AS (f1:int, f2:int, f3:int), group;
В этом примере оператор FOREACH включает схему для простого выражения.
X = FOREACH A GENERATE f1+f2 AS x1:int;
В этом примере оператор FOREACH включает схемы для нескольких полей.
X = FOREACH A GENERATE f1 as user, f2 as age, f3 as gpa;
Схемы для простых типов данных
Простые типы данных включают int, long, float, double, chararray, bytearray, boolean, datetime, biginteger и bigdecimal.
Синтаксис
| (alias[:type]) [, (alias[:type]) …] ) |
Термины
| alias | Назначенное имя поля. |
| type | (Необязательно) Назначенный простой тип данных поля. Имя и тип разделены двоеточием ( : ). Если тип опущен, поле по умолчанию имеет тип bytearray. |
| ( , ) | Несколько полей заключены в скобки и разделены запятыми. |
Примеры
В этом примере схема определяет несколько типов.
cat student;
John 18 4.0
Mary 19 3.8
Bill 20 3.9
Joe 18 3.8
A = LOAD 'student' AS (name:chararray, age:int, gpa:float);
DESCRIBE A;
A: {name: chararray,age: int,gpa: float}
DUMP A;
(John,18,4.0F)
(Mary,19,3.8F)
(Bill,20,3.9F)
(Joe,18,3.8F)
В этом примере поле "gpa" по умолчанию будет иметь тип bytearray, так как тип не объявлен.
cat student;
John 18 4.0
Mary 19 3.8
Bill 20 3.9
Joe 18 3.8
A = LOAD 'data' AS (name:chararray, age:int, gpa);
DESCRIBE A;
A: {name: chararray,age: int,gpa: bytearray}
DUMP A;
(John,18,4.0)
(Mary,19,3.8)
(Bill,20,3.9)
(Joe,18,3.8)
Схемы для сложных типов данных
Сложные типы данных включают кортежи, множества и карты.
Схемы кортежей
Кортеж — упорядоченный набор полей.
Синтаксис
| alias[:tuple] (alias[:type]) [, (alias[:type]) …] ) |
Термины
| alias | Назначенное имя кортежа. |
| :tuple | (Необязательно) Тип данных, кортеж (регистр не учитывается). |
| ( ) | Определение кортежа, набор скобок. |
| alias[:type] | Составные части кортежа, где правила определения схемы для соответствующего типа применяются к составляющим частям кортежа:
|
Примеры
В этом примере схема определяет одну кортеж. Операторы загрузки эквивалентны.
cat data;
(3,8,9)
(1,4,7)
(2,5,8)
A = LOAD 'data' AS (T: tuple (f1:int, f2:int, f3:int));
A = LOAD 'data' AS (T: (f1:int, f2:int, f3:int));
DESCRIBE A;
A: {T: (f1: int,f2: int,f3: int)}
DUMP A;
((3,8,9))
((1,4,7))
((2,5,8))
В этом примере схема определяет две кортежи.
cat data;
(3,8,9) (mary,19)
(1,4,7) (john,18)
(2,5,8) (joe,18)
A = LOAD data AS (F:tuple(f1:int,f2:int,f3:int),T:tuple(t1:chararray,t2:int));
DESCRIBE A;
A: {F: (f1: int,f2: int,f3: int),T: (t1: chararray,t2: int)}
DUMP A;
((3,8,9),(mary,19))
((1,4,7),(john,18))
((2,5,8),(joe,18))
Схемы мешков
Мешок — это коллекция кортежей.
Синтаксис
| псевдоним[:мешок] {кортеж} |
Термины
| псевдоним | Имя, присвоенное мешку. |
| :мешок | (Необязательно) Тип данных, мешок (регистр не учитывается). |
| { } | Обозначение для мешка, набор фигурных скобок. |
| кортеж | Кортеж (см. Схему кортежа). |
Примеры
В этом примере схема определяет мешок. Два оператора загрузки эквивалентны.
cat data;
{(3,8,9)}
{(1,4,7)}
{(2,5,8)}
A = LOAD 'data' AS (B: bag {T: tuple(t1:int, t2:int, t3:int)});
A = LOAD 'data' AS (B: {T: (t1:int, t2:int, t3:int)});
DESCRIBE A:
A: {B: {T: (t1: int,t2: int,t3: int)}}
DUMP A;
({(3,8,9)})
({(1,4,7)})
({(2,5,8)})
Схемы словарей
Словарь — это набор пар «ключ-значение».
Синтаксис (<> обозначает необязательность)
| псевдоним<:словарь> [ <тип> ] |
Термины
| псевдоним | Имя, присвоенное словарю. |
| :словарь | (Необязательно) Тип данных, словарь (регистр не учитывается). |
| [ ] | Обозначение для словаря, набор квадратных скобок. |
| тип | (Необязательно) Тип данных (допускаются все типы, по умолчанию bytearray). Тип применяется только к значению словаря; ключ словаря всегда типа chararray (см. Словарь). Если тип объявлен, все значения в словаре должны быть этого типа. |
Примеры
В этом примере схема определяет словарь без указания типа (значения словаря по умолчанию bytearray). Операторы загрузки эквивалентны.
cat data;
[open#apache]
[apache#hadoop]
A = LOAD 'data' AS (M:map []);
A = LOAD 'data' AS (M:[]);
DESCRIBE A;
a: {M: map[ ]}
DUMP A;
([open#apache])
([apache#hadoop])
Этот пример демонстрирует использование словарей со спецификацией типа.
/* Map types are declared*/
a = load '1.txt' as(map[int]); --Map value is int
b = foreach a generate (map[(i:int)])a0; -- Map value is tuple
b = stream a through `cat` as (m:map[{(i:int,j:chararray)}]); -- Map value is bag
/* The MapLookup of a typed map will result in a datatype of the map value */
a = load '1.txt' as(map[int]);
b = foreach a generate $0#'key';
/* Schema for b */
b: {int}
Схемы для нескольких типов
Вы можете определить схемы для данных, включающих несколько типов.
Пример
В этом примере схема определяет кортеж, мешок и словарь.
A = LOAD 'mydata' AS (T1:tuple(f1:int, f2:int), B:bag{T2:tuple(t1:float,t2:float)}, M:map[] );
A = LOAD 'mydata' AS (T1:(f1:int, f2:int), B:{T2:(t1:float,t2:float)}, M:[] );
Сокращение ссылки на предыдущую таблицу
Существует сокращенная форма для ссылки на таблицу на предыдущей строке скрипта Pig или сеанса grunt:
a = load 'thing' as (x:int); b = foreach @ generate x; c = foreach @ generate x; d = foreach @ generate x;
Арифметические операторы и многое другое
Арифметические операторы
Описание
| Оператор | Символ | Примечания |
| сложение | + | |
| вычитание | - | |
| умножение | * | |
| деление | / | |
| остаток от деления | % | Возвращает остаток от деления a на b (a%b). Работает с целыми числами (int, long). |
| условный оператор | ? : | (условие ? значение_если_истина : значение_если_ложь) Условный оператор должен быть заключен в скобки. Схемы двух условных выходных значений должны совпадать. Используйте только выражения (реляционные операторы недопустимы). |
| case | CASE WHEN THEN ELSE END | CASE выражение [ WHEN значение THEN значение ]+ [ ELSE значение ]? END CASE [ WHEN условие THEN значение ]+ [ ELSE значение ]? END Оператор CASE эквивалентен вложенным условным операторам. Схемы всех выходных значений ветвей when/else должны совпадать. Используйте только выражения (реляционные операторы недопустимы). |
Примеры
Предположим, у нас есть таблица A.
A = LOAD 'data' AS (f1:int, f2:int, B:bag{T:tuple(t1:int,t2:int)});
DUMP A;
(10,1,{(2,3),(4,6)})
(10,3,{(2,3),(4,6)})
(10,6,{(2,3),(4,6),(5,7)})
В этом примере оператор остатка от деления используется с полями f1 и f2.
X = FOREACH A GENERATE f1, f2, f1%f2; DUMP X; (10,1,0) (10,3,1) (10,6,4)
В этом примере условный оператор используется с полями f2 и B. Условие — "f2 равно 1"; если условие истинно, возвращается 1; если ложно, возвращается количество кортежей в B.
X = FOREACH A GENERATE f2, (f2==1?1:COUNT(B)); DUMP X; (1,1L) (3,2L) (6,3L)
В этом примере оператор case используется с полем f2. Выражение — "f2 % 2"; если выражение равно 0, возвращается 'even'; если равно 1, возвращается 'odd'.
X = FOREACH A GENERATE f2, (
CASE f2 % 2
WHEN 0 THEN 'even'
WHEN 1 THEN 'odd'
END
);
DUMP X;
(1,odd)
(3,odd)
(6,even)
Это также можно записать следующим образом:
X = FOREACH A GENERATE f2, (
CASE
WHEN f2 % 2 == 0 THEN 'even'
WHEN f2 % 2 == 1 THEN 'odd'
END
);
DUMP X;
(1,odd)
(3,odd)
(6,even)
Таблица типов: операторы сложения (+) и вычитания (-)
* bytearray преобразуется к этому типу данных
| мешок | кортеж | словарь | int | long | float | double | chararray | bytearray | |
| мешок | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка |
| кортеж | нет еще | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| словарь | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ||
| int | int | long | float | double | ошибка | преобразование в int | |||
| ... |
Таблица типов: операторы умножения (*) и деления (/)
* bytearray преобразуется к этому типу данных
| мешок | кортеж | карта | целое | длинное | вещественное | двойное | символьный массив | байтовый массив | |
| мешок | ошибка | ошибка | ошибка | ещё нет | ещё нет | ещё нет | ещё нет | ошибка | ошибка |
| кортеж | ошибка | ошибка | ещё нет | ещё нет | ещё нет | ещё нет | ошибка | ошибка | |
| карта | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ||
| целое | целое | длинное | вещественное | двойное | ошибка | привести к целому | |||
| длинное | длинное | вещественное | двойное | ошибка | привести к длинному | ||||
| вещественное | вещественное | двойное | ошибка | привести к вещественному | |||||
| двойное | двойное | ошибка | привести к двойному | ||||||
| символьный массив | ошибка | ошибка | |||||||
| байтовый массив | привести к двойному |
Таблица типов: оператор modulo (%)
| целое | длинное | байтовый массив | |
| целое | целое | длинное | привести к целому |
| длинное | длинное | привести к длинному | |
| байтовый массив | ошибка |
Булевы операторы
Описание
| Оператор | Символ | Примечания |
| И | и | |
| ИЛИ | или | |
| В | в | Оператор В эквивалентен вложенным операторам ИЛИ. |
| НЕ | не |
Результат булевого выражения (выражения, включающего булевы и сравнения операторы) всегда имеет тип boolean (true или false).
Пример
X = FILTER A BY (f1==8) OR (NOT (f2+f3 > f1)) OR (f1 IN (9, 10, 11));
Операторы приведения типов
Описание
Pig Latin поддерживает приведение типов, как показано в этой таблице.
| от / до | мешок | кортеж | карта | int | long | float | double | chararray | bytearray | boolean |
| мешок | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| кортеж | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| карта | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| int | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| long | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| float | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| double | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| chararray | ошибка | ошибка | ошибка | да | да | да | да | ошибка | да | |
| bytearray | да | да | да | да | да | да | да | да | да | |
| boolean | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | да | ошибка |
Синтаксис
| {(тип_данных) | (кортеж(тип_данных)) | (мешок{кортеж(тип_данных)}) | (карта[]) } поле |
Термины
| (тип_данных) | Тип данных, к которому вы хотите привести, заключенный в скобки. Вы можете привести к любому типу данных, кроме bytearray (см. таблицу выше). |
| поле | Поле, тип которого вы хотите изменить. Поле может быть представлено позиционной нотацией или по имени (псевдонимом). Например, если f1 — первое поле типа int, вы можете привести его к типу long, используя (long)$0 или (long)f1. |
Использование
Операторы приведения позволяют привести или преобразовать данные из одного типа в другой, если преобразование поддерживается (см. таблицу выше). Например, предположим, что у вас есть поле целого типа myint, которое вы хотите преобразовать в строку. Вы можете привести это поле из int в chararray, используя (chararray)myint.
Обратите внимание на следующее:
-
Поле можно явно привести к другому типу. После приведения поле остается этого типа (автоматического приведения обратно не происходит). В данном примере $0 явно приводится к типу int.
B = FOREACH A GENERATE (int)$0 + 1;
-
Когда это возможно, Pig выполняет неявные приведения. В данном примере $0 приводится к int (независимо от исходных данных), а $1 приводится к double.
B = FOREACH A GENERATE $0 + 1, $1 + 1.0
-
Когда два bytearray используются в арифметических выражениях или выражение bytearray используется с встроенными агрегатными функциями (такими как SUM), они неявно приводятся к double. Если основополагающие данные на самом деле int или long, вы получите лучшую производительность, объявив тип или явно приведя данные.
-
Приведение может привести к потере данных. Например, приведение от long к int может привести к потере битов.
Примеры
В этом примере int приводится к типу chararray (см. отношение X).
A = LOAD 'data' AS (f1:int,f2:int,f3:int);
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
(7,2,5)
(8,4,3)
B = GROUP A BY f1;
DUMP B;
(1,{(1,2,3)})
(4,{(4,2,1),(4,3,3)})
(7,{(7,2,5)})
(8,{(8,3,4),(8,4,3)})
DESCRIBE B;
B: {group: int,A: {f1: int,f2: int,f3: int}}
X = FOREACH B GENERATE group, (chararray)COUNT(A) AS total;
(1,1)
(4,2)
(7,1)
(8,2)
DESCRIBE X;
X: {group: int,total: chararray}
В этом примере bytearray (fld в отношении A) приводится к типу кортежа.
cat data;
(1,2,3)
(4,2,1)
(8,3,4)
A = LOAD 'data' AS fld:bytearray;
DESCRIBE A;
a: {fld: bytearray}
DUMP A;
((1,2,3))
((4,2,1))
((8,3,4))
B = FOREACH A GENERATE (tuple(int,int,float))fld;
DESCRIBE B;
b: {(int,int,float)}
DUMP B;
((1,2,3))
((4,2,1))
((8,3,4))
В этом примере bytearray (fld в отношении A) приводится к типу мешка.
cat data;
{(4829090493980522200L)}
{(4893298569862837493L)}
{(1297789302897398783L)}
A = LOAD 'data' AS fld:bytearray;
DESCRIBE A;
A: {fld: bytearray}
DUMP A;
({(4829090493980522200L)})
({(4893298569862837493L)})
({(1297789302897398783L)})
B = FOREACH A GENERATE (bag{tuple(long)})fld;
DESCRIBE B;
B: {{(long)}}
DUMP B;
({(4829090493980522200L)})
({(4893298569862837493L)})
({(1297789302897398783L)})
В этом примере bytearray (fld в отношении A) приводится к типу карты.
cat data;
[open#apache]
[apache#hadoop]
[hadoop#pig]
[pig#grunt]
A = LOAD 'data' AS fld:bytearray;
DESCRIBE A;
A: {fld: bytearray}
DUMP A;
([open#apache])
([apache#hadoop])
([hadoop#pig])
([pig#grunt])
B = FOREACH A GENERATE ((map[])fld;
DESCRIBE B;
B: {map[ ]}
DUMP B;
([open#apache])
([apache#hadoop])
([hadoop#pig])
([pig#grunt])
Приведение Отношений к Скалярам
Pig позволяет привести элементы отношения с одним кортежем к скалярному значению. Кортеж может быть однопольным или многопольным. Однако, если отношение содержит более одного кортежа, генерируется ошибка выполнения: "Скаляр имеет более одной строки в выводе".
Приведенное отношение может использоваться в любом месте, где выражение соответствующего типа имеет смысл, включая FOREACH, FILTER и SPLIT. Обратите внимание, что если явное приведение не используется, будет выполнено неявное приведение в соответствии с правилами Pig. Также, когда схема не может быть определена, используется bytearray.
Основное применение приведения отношений к скалярам заключается в возможности использования значений глобальных агрегатов в последующих вычислениях.
В этом примере вычисляется процент кликов, принадлежащих конкретному пользователю. Для оператора FOREACH используется явное приведение. Если SUM не получает имя, можно использовать и позицию (userid, clicks/(double)C.$0).
A = load 'mydata' as (userid, clicks); B = group A all; C = foreach B genertate SUM(A.clicks) as total; D = foreach A generate userid, clicks/(double)C.total; dump D;
В этом примере используется многопольный кортеж. Для оператора FILTER Pig выполняет неявное приведение. Для оператора FOREACH используется явное приведение.
A = load 'mydata' as (userid, clicks); B = group A all; C = foreach B genertate SUM(A.clicks) as total, COUNT(A) as cnt; D = FILTER A by clicks > C.total/3 E = foreach D generate userid, clicks/(double)C.total, cnt; dump E;
Операторы Сравнения
Описание
| Оператор | Символ | Примечания |
| равно | == | |
| не равно | != | |
| меньше | < | |
| больше | > | |
| меньше или равно | <= | |
| больше или равно | >= | |
| совпадение с шаблоном | matches | Принимает выражение слева и строковую константу справа. выражение matches строковая-константа Используйте формат Java формат для регулярных выражений. |
Используйте операторы сравнения с числовыми и строковыми данными.
Примеры
Числовой пример
X = FILTER A BY (f1 == 8);
Строковый пример
X = FILTER A BY (f2 == 'apache');
Пример совпадения
X = FILTER A BY (f1 matches '.*apache.*');
Таблица типов: оператор равно (==)
| bag | tuple | map | int | long | float | double | chararray | bytearray | boolean | datetime | biginteger | bigdecimal | |
| bag | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка |
| tuple | boolean (см. Примечание 1) | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| map | boolean (см. Примечание 2) | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ||
| int | boolean | boolean | boolean | boolean | ошибка | преобразование к boolean | ошибка | ошибка | ошибка | ошибка | |||
| long | boolean | boolean | boolean | ошибка | преобразование к boolean | ошибка | ошибка | ошибка | ошибка | ||||
| float | boolean | boolean | ошибка | преобразование к boolean | ошибка | ошибка | ошибка | ошибка | |||||
| double | boolean | ошибка | преобразование к boolean | ошибка | ошибка | ошибка | ошибка | ||||||
| chararray | boolean | преобразование к boolean | ошибка | ошибка | ошибка | ошибка | |||||||
| bytearray | boolean | ошибка | ошибка | ошибка | ошибка | ||||||||
| boolean | boolean | ошибка | ошибка | ошибка | |||||||||
| datetime | boolean | ошибка | ошибка | ||||||||||
| biginteger | boolean | ошибка | |||||||||||
| bigdecimal | boolean |
Примечание 1: boolean (Кортеж A равен кортежу B, если они имеют одинаковый размер s, и для всех 0 <= i < s A[i] == B[i])
Примечание 2: boolean (Словарь A равен словарю B, если A и B имеют одинаковое количество записей, и для каждого ключа k1 в A со значением v1 существует ключ k2 в B со значением v2, такой что k1 == k2 и v1 == v2)
Таблица типов: оператор неравенства (!=)
| bag | кортеж | отображение | int | long | float | double | chararray | bytearray | boolean | datetime | biginteger | bigdecimal | |
| bag | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка |
| кортеж | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| отображение | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ||
| int | boolean | boolean | boolean | boolean | ошибка | boolean (bytearray преобразован к int) | ошибка | ошибка | ошибка | ошибка | |||
| long | boolean | boolean | boolean | ошибка | boolean (bytearray преобразован к long) | ошибка | ошибка | ошибка | ошибка | ||||
| float | boolean | boolean | ошибка | boolean (bytearray преобразован к float) | ошибка | ошибка | ошибка | ошибка | |||||
| double | boolean | ошибка | boolean (bytearray преобразован к double) | ошибка | ошибка | ошибка | ошибка | ||||||
| chararray | boolean | boolean (bytearray преобразован к chararray) | ошибка | ошибка | ошибка | ошибка | |||||||
| bytearray | boolean | ошибка | ошибка | ошибка | ошибка | ||||||||
| boolean | boolean | ошибка | ошибка | ошибка | |||||||||
| datetime | boolean | ошибка | ошибка | ||||||||||
| biginteger | boolean | ошибка | |||||||||||
| bigdecimal | boolean |
Таблица типов: оператор matches
*Преобразовано как chararray (второй аргумент должен быть chararray)
| chararray | bytearray* | |
| chararray | boolean | boolean |
| bytearray | boolean | boolean |
Операторы построения типов
Описание
| Оператор | Символ | Примечания |
| конструктор кортежа | ( ) | Используется для построения кортежа из указанных элементов. Эквивалентно TOTUPLE. |
| конструктор bag | { } | Используется для построения bag из указанных элементов. Эквивалентно TOBAG. |
| конструктор отображения | [ ] | Используется для построения отображения из указанных элементов. Эквивалентно TOMAP. |
Обратите внимание на следующее:
- Эти операторы могут быть использованы везде, где допустимо выражение соответствующего типа, включая FOREACH, GENERATE, FILTER и т.д.
- Один элемент в скобках ( ) например (5) не считается кортежем, а скорее арифметическим оператором.
- Для bag каждый элемент помещается в bag; если элемент не является кортежем, Pig создаст кортеж для него:
- Данный {$1, $2} Pig создаст {($1), ($2)} bag с двумя кортежами
... ни $1, ни $2 не являются кортежами, поэтому Pig создаёт кортеж вокруг каждого элемента
- Данный {($1), $2} Pig создаст {($1), ($2)} bag с двумя кортежами
... так как ($1) обрабатывается как $1 (нельзя создать кортеж из одного элемента с помощью этого синтаксиса), {($1), $2} становится {$1, $2}, и Pig создаёт кортеж вокруг каждого элемента
- Данный {($1, $2)} Pig создаст {($1, $2)} bag с одним кортежем
... Pig создаёт кортеж ($1, $2) и затем помещает этот кортеж в bag
- Данный {$1, $2} Pig создаст {($1), ($2)} bag с двумя кортежами
Примеры
Построение кортежа
A = load 'students' as (name:chararray, age:int, gpa:float); B = foreach A generate (name, age); store B into 'results'; Input (students): joe smith 20 3.5 amy chen 22 3.2 leo allen 18 2.1 Output (results): (joe smith,20) (amy chen,22) (leo allen,18)
Построение bag
A = load 'students' as (name:chararray, age:int, gpa:float);
B = foreach A generate {(name, age)}, {name, age};
store B into 'results';
Input (students):
joe smith 20 3.5
amy chen 22 3.2
leo allen 18 2.1
Output (results):
{(joe smith,20)} {(joe smith),(20)}
{(amy chen,22)} {(amy chen),(22)}
{(leo allen,18)} {(leo allen),(18)}
Построение отображения
A = load 'students' as (name:chararray, age:int, gpa:float); B = foreach A generate [name, gpa]; store B into 'results'; Input (students): joe smith 20 3.5 amy chen 22 3.2 leo allen 18 2.1 Output (results): [joe smith#3.5] [amy chen#3.2] [leo allen#2.1]
Операторы ссылки
Описание
| Оператор | Символ | Примечания |
| разыменование кортежа | tuple.id или tuple.(id,…) | Разыменование кортежа может выполняться по имени (tuple.field_name) или по позиции (mytuple.$0). Если разыменовывается набор полей (tuple.(name1, name2) или tuple.($0, $1)), выражение представляет собой кортеж, составленный из указанных полей. Обратите внимание, что если оператор точки применяется к bytearray, то bytearray будет считаться кортежем. |
| разыменование мешка | bag.id или bag.(id,…) | Разыменование мешка может выполняться по имени (bag.field_name) или по позиции (bag.$0). Если разыменовывается набор полей (bag.(name1, name2) или bag.($0, $1)), выражение представляет собой мешок, составленный из указанных полей. |
| разыменование карты | map#'key' | Разыменование карты должно выполняться по ключу (field_name#key или $0#key). Если оператор фунта применяется к bytearray, то bytearray считается картой. Если ключ не существует, возвращается пустая строка. |
Примеры
Пример с кортежем
Предположим, у нас есть отношение A.
A = LOAD 'data' as (f1:int, f2:tuple(t1:int,t2:int,t3:int)); DUMP A; (1,(1,2,3)) (2,(4,5,6)) (3,(7,8,9)) (4,(1,4,7)) (5,(2,5,8))
В этом примере разыменование используется для получения двух полей из кортежа f2.
X = FOREACH A GENERATE f2.t1,f2.t3; DUMP X; (1,3) (4,6) (7,9) (1,7) (2,8)
Пример с мешком
Предположим, у нас есть отношение B, образованное группировкой отношения A (см. оператор GROUP для получения информации о именах полей в отношении B).
A = LOAD 'data' AS (f1:int, f2:int,f3:int);
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
(7,2,5)
(8,4,3)
B = GROUP A BY f1;
DUMP B;
(1,{(1,2,3)})
(4,{(4,2,1),(4,3,3)})
(7,{(7,2,5)})
(8,{(8,3,4),(8,4,3)})
ILLUSTRATE B;
etc …
----------------------------------------------------------
| b | group: int | a: bag({f1: int,f2: int,f3: int}) |
----------------------------------------------------------
В этом примере разыменование используется с отношением X для проектирования первого поля (f1) каждого кортежа в мешке (a).
X = FOREACH B GENERATE a.f1;
DUMP X;
({(1)})
({(4),(4)})
({(7)})
({(8),(8)})
Пример с кортежем/мешком
Предположим, у нас есть отношение B, образованное группировкой отношения A (см. оператор GROUP для получения информации о именах полей в отношении B).
A = LOAD 'data' AS (f1:int, f2:int, f3:int);
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
(7,2,5)
(8,4,3)
B = GROUP A BY (f1,f2);
DUMP B;
((1,2),{(1,2,3)})
((4,2),{(4,2,1)})
((4,3),{(4,3,3)})
((7,2),{(7,2,5)})
((8,3),{(8,3,4)})
((8,4),{(8,4,3)})
ILLUSTRATE B;
etc …
-------------------------------------------------------------------------------
| b | group: tuple({f1: int,f2: int}) | a: bag({f1: int,f2: int,f3: int}) |
-------------------------------------------------------------------------------
| | (8, 3) | {(8, 3, 4), (8, 3, 4)} |
-------------------------------------------------------------------------------
В этом примере разыменование используется для проектирования поля (f1) из кортежа (группы) и поля (f1) из мешка (a).
X = FOREACH B GENERATE group.f1, a.f1;
DUMP X;
(1,{(1)})
(4,{(4)})
(4,{(4)})
(7,{(7)})
(8,{(8)})
(8,{(8)})
Пример с картой
Предположим, у нас есть отношение A.
A = LOAD 'data' AS (f1:int, f2:map[]); DUMP A; (1,[open#apache]) (2,[apache#hadoop]) (3,[hadoop#pig]) (4,[pig#grunt])
В этом примере разыменование используется для поиска значения ключа 'open'.
X = FOREACH A GENERATE f2#'open'; DUMP X; (apache) () () ()
Оператор разыменования
Используйте оператор разыменования ( :: ) для идентификации имен полей после операторов JOIN, COGROUP, CROSS или FLATTEN.
В этом примере, чтобы разыменовать y, используйте A::y или B::y. В случаях, когда нет неоднозначности, например, z, оператор :: не требуется, но всё ещё поддерживается.
A = load 'data1' as (x, y); B = load 'data2' as (x, y, z); C = join A by x, B by x; D = foreach C generate y; -- which y?
Оператор FLATTEN
Оператор FLATTEN синтаксически похож на UDF, но на самом деле это оператор, который изменяет структуру кортежей и мешков таким образом, как это не может сделать UDF. FLATTEN распаковывает кортежи и мешки.
Для кортежей FLATTEN заменяет поля кортежа на место кортежа. Например, рассмотрим отношение с кортежем вида (a, (b, c)). Выражение GENERATE $0, flatten($1) заставит этот кортеж стать (a, b, c).
Для мешков ситуация становится более сложной. Когда мы распаковываем мешок, мы создаём новые кортежи. Если у нас есть отношение, состоящее из кортежей вида ({(b,c),(d,e)}) и мы применяем GENERATE flatten($0), мы получим два кортежа (b,c) и (d,e). При удалении уровня вложенности в мешке иногда происходит перекрёстное произведение. Например, рассмотрим отношение с кортежем вида (a, {(b,c), (d,e)}), обычно создаваемое оператором GROUP. Если мы применим выражение GENERATE $0, flatten($1) к этому кортежу, мы создадим новые кортежи: (a, b, c) и (a, d, e).
Обратите также внимание, что FLATTEN пустого мешка приведёт к тому, что строка будет отброшена; вывод не будет сгенерирован. (См. также Исключить Null перед соединением.)
grunt> cat empty.bag
{} 1
grunt> A = LOAD 'empty.bag' AS (b : bag{}, i : int);
grunt> B = FOREACH A GENERATE flatten(b), i;
grunt> DUMP B;
grunt>
Примеры использования оператора FLATTEN см. в разделе FOREACH.
Операторы Null
Описание
| Оператор | Символ | Примечания |
| равен null | равен null | |
| не равен null | не равен null |
Подробное обсуждение null см. в Null и Pig Latin.
Примеры
В этом примере получаются значения, не равные null.
X = FILTER A BY f1 is not null;
Таблица типов
Операторы null могут применяться ко всем типам данных (см. Null и Pig Latin).
Операторы знака
Описание
| Оператор | Символ | Примечания |
| положительный | + | Не оказывает никакого влияния. |
| отрицательный (отрицание) | - | Изменяет знак положительного или отрицательного числа. |
Примеры
В этом примере оператор отрицания применяется к значениям "x".
A = LOAD 'data' as (x, y, z); B = FOREACH A GENERATE -x, y;
Таблица типов: оператор отрицания ( - )
| мешок | ошибка |
| кортеж | ошибка |
| карта | ошибка |
| int | int |
| long | long |
| float | float |
| double | double |
| chararray | ошибка |
| bytearray | double (как double) |
| datetime | ошибка |
| biginteger | biginteger |
| bigdecimal | bigdecimal |
Операторы отношений
ASSERT
Проверить условие на данных.
Синтаксис
| ASSERT alias BY выражение [, сообщение]; |
Термины
| alias | Имя отношения. |
| BY | Обязательное ключевое слово. |
| выражение | Булево выражение. |
| сообщение | Сообщение об ошибке при нарушении утверждения. |
Использование
Используйте assert, чтобы убедиться, что условие истинно для ваших данных. Обработка завершается неудачно, если какие-либо записи нарушают условие.
Примеры
Предположим, что у нас есть отношение A.
A = LOAD 'data' AS (a0:int,a1:int,a2:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3)
Теперь вы можете утверждать, что столбец a0 в ваших данных больше 0, и завершить выполнение с ошибкой в противном случае
ASSERT A by a0 > 0, 'a0 should be greater than 0';
COGROUP
См. оператор GROUP.
CROSS
Вычисляет декартово произведение двух или более отношений.
Синтаксис
| alias = CROSS alias, alias [, alias …] [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| PARTITION BY partitioner | Используйте эту функцию для указания Hadoop Partitioner. Partitioner управляет разделением ключей промежуточных результатов map-вычислений.
|
| PARALLEL n | Увеличьте параллельность задачи, указав количество задач reduce, n. Дополнительные сведения см. в Использование параллельных функций. |
Использование
Используйте оператор CROSS для вычисления декартова произведения двух или более отношений.
CROSS — это дорогостоящая операция, и ее следует использовать экономно.
Пример
Предположим, что у нас есть отношения A и B.
A = LOAD 'data1' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) B = LOAD 'data2' AS (b1:int,b2:int); DUMP B; (2,4) (8,9) (1,3)
В этом примере вычисляется декартово произведение отношения A и B.
X = CROSS A, B; DUMP X; (1,2,3,2,4) (1,2,3,8,9) (1,2,3,1,3) (4,2,1,2,4) (4,2,1,8,9) (4,2,1,1,3)
CUBE
Выполняет операции cube/rollup.
Операция cube
Операция cube вычисляет агрегаты для всех возможных комбинаций указанных измерений группировки. Количество комбинаций группировки, генерируемых cube для n измерений, будет равно 2^n.
Операция rollup
Операция rollup вычисляет несколько уровней агрегатов на основе иерархической упорядоченности указанных измерений группировки. Rollup полезен, когда существуют иерархические упорядочения по измерениям. Количество комбинаций группировки, генерируемых rollup для n измерений, будет равно n+1.
Синтаксис
| alias = CUBE alias BY { CUBE выражение | ROLLUP выражение }, [ CUBE выражение | ROLLUP выражение ] [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| CUBE | Ключевое слово |
| BY | Ключевое слово |
| выражение | Проекции (измерения) отношения. Поддерживает выражения для полей, звёзд и диапазонов. |
| ROLLUP | Ключевое слово |
| PARALLEL n | Увеличьте параллельность задачи, указав количество задач reduce, n. Дополнительные сведения см. в Использование параллельных функций. |
Пример
Базовое использование операции CUBE
salesinp = LOAD '/pig/data/salesdata' USING PigStorage(',') AS
(product:chararray, year:int, region:chararray, state:chararray, city:chararray, sales:long);
cubedinp = CUBE salesinp BY CUBE(product,year);
result = FOREACH cubedinp GENERATE FLATTEN(group), SUM(cube.sales) AS totalsales; Для входной кортежи (car, 2012, midwest, ohio, columbus, 4000) вышеприведенный запрос с операцией cube даст на выходе
(car,2012,4000) (car,,4000) (,2012,4000) (,,4000)
Схема вывода
grunt> describe cubedinp;
cubedinp: {group: (product: chararray,year: int),cube: {(product: chararray,year: int,region: chararray,
state: chararray,city: chararray,sales: long)}} Обратите внимание на второй столбец, поле ‘cube’, которое представляет собой множество всех кортежей, относящихся к ‘группе’. Также обратите внимание, что атрибут измерения ‘sales’, наряду с другими неиспользуемыми измерениями в операторе load, отсылается вниз, чтобы его можно было использовать позднее при вычислении агрегатов по измерению, как в данном случае SUM(cube.sales).
Базовое использование операции ROLLUP
salesinp = LOAD '/pig/data/salesdata' USING PigStorage(',') AS
(product:chararray, year:int, region:chararray, state:chararray, city:chararray, sales:long);
rolledup = CUBE salesinp BY ROLLUP(region,state,city);
result = FOREACH rolledup GENERATE FLATTEN(group), SUM(cube.sales) AS totalsales; Для входной кортежи (car, 2012, midwest, ohio, columbus, 4000) вышеприведенный запрос с операцией rollup даст на выходе
(midwest,ohio,columbus,4000) (midwest,ohio,,4000) (midwest,,,4000) (,,,4000)
Схема вывода
grunt> describe rolledup;
rolledup: {group: (region: chararray,state: chararray,city: chararray),cube: {(region: chararray,
state: chararray,city: chararray,product: chararray,year: int,sales: long)}} Базовое использование операций CUBE и ROLLUP совместно
Если операции CUBE и ROLLUP используются вместе, группы вывода будут представлять декартово произведение всех групп, сгенерированных операциями cube и rollup. Если в операциях cube есть m измерений, а в операциях rollup — n, то общее количество комбинаций составит (2^m) * (n+1).
salesinp = LOAD '/pig/data/salesdata' USING PigStorage(',') AS
(product:chararray, year:int, region:chararray, state:chararray, city:chararray, sales:long);
cubed_and_rolled = CUBE salesinp BY CUBE(product,year), ROLLUP(region, state, city);
result = FOREACH cubed_and_rolled GENERATE FLATTEN(group), SUM(cube.sales) AS totalsales; Для входной кортежи (car, 2012, midwest, ohio, columbus, 4000) вышеприведенный запрос с операциями cube и rollup даст на выходе
(car,2012,midwest,ohio,columbus,4000) (car,2012,midwest,ohio,,4000) (car,2012,midwest,,,4000) (car,2012,,,,4000) (car,,midwest,ohio,columbus,4000) (car,,midwest,ohio,,4000) (car,,midwest,,,4000) (car,,,,,4000) (,2012,midwest,ohio,columbus,4000) (,2012,midwest,ohio,,4000) (,2012,midwest,,,4000) (,2012,,,,4000) (,,midwest,ohio,columbus,4000) (,,midwest,ohio,,4000) (,,midwest,,,4000) (,,,,,4000)
Схема вывода
grunt> describe cubed_and_rolled;
cubed_and_rolled: {group: (product: chararray,year: int,region: chararray,
state: chararray,city: chararray),cube: {(product: chararray,year: int,region: chararray,
state: chararray,city: chararray,sales: long)}} Обработка пустых значений в измерениях
Поскольку пустые значения используются для представления подсчетов в операциях cube и rollup, для того чтобы отличить законные пустые значения, которые уже существуют в качестве значений измерений, оператор CUBE преобразует все пустые значения в измерения в значение "unknown" перед выполнением операций cube или rollup. Например, для CUBE(product,location) с образцовой кортежей (car,) на выходе будет
(car,unknown) (car,) (,unknown) (,)
DEFINE
См.:
DISTINCT
Удаляет дублирующиеся кортежи в отношении.
Синтаксис
| alias = DISTINCT alias [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| PARTITION BY partitioner | Используйте эту функцию для указания Hadoop Partitioner. Partitioner управляет разделением ключей промежуточных результатов map-вычислений.
|
| PARALLEL n | Увеличьте параллельность задачи, указав количество задач reduce, n. Дополнительные сведения см. в Использование параллельных функций. |
Использование
Используйте оператор DISTINCT для удаления дублирующихся кортежей в отношении. DISTINCT не сохраняет исходный порядок содержимого (для удаления дубликатов Pig должен сначала отсортировать данные). Вы не можете использовать DISTINCT для подмножества полей; для этого используйте FOREACH и вложенный блок, чтобы сначала выбрать поля, а затем применить DISTINCT (см. Пример: Вложенный блок).
Пример
Предположим, что у нас есть отношение A.
A = LOAD 'data' AS (a1:int,a2:int,a3:int); DUMP A; (8,3,4) (1,2,3) (4,3,3) (4,3,3) (1,2,3)
В этом примере удаляются все дублирующиеся кортежи.
X = DISTINCT A; DUMP X; (1,2,3) (4,3,3) (8,3,4)
FILTER
Выбирает кортежи из отношения на основе некоторого условия.
Синтаксис
| alias = FILTER alias BY выражение; |
Термины
| alias | Имя отношения. |
| BY | Обязательное ключевое слово. |
| выражение | Булево выражение. |
Использование
Используйте оператор FILTER для работы с кортежами или строками данных (если вы хотите работать со столбцами данных, используйте операцию FOREACH...GENERATE).
FILTER обычно используется для выбора необходимых данных или, наоборот, для фильтрации (удаления) ненужных данных.
Примеры
Предположим, что у нас есть отношение A.
A = LOAD 'data' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3)
В этом примере условие гласит, что если третье поле равно 3, то включите кортеж с отношением X.
X = FILTER A BY f3 == 3; DUMP X; (1,2,3) (4,3,3) (8,4,3)
В этом примере условие гласит, что если первое поле равно 8 или сумма полей f2 и f3 не больше первого поля, то включите кортеж отношения X.
X = FILTER A BY (f1 == 8) OR (NOT (f2+f3 > f1)); DUMP X; (4,2,1) (8,3,4) (7,2,5) (8,4,3)
FOREACH
Генерирует преобразования данных на основе столбцов данных.
Синтаксис
| alias = FOREACH { block | nested_block }; |
Термины
| псевдоним | Имя отношения (внешний пакет). |
| блок | блок FOREACH…GENERATE, используемый с отношением (внешний пакет). Используйте этот синтаксис: псевдоним = FOREACH псевдоним GENERATE выражение [КАК схема] [выражение [КАК схема]….]; См. Схемы |
| вложенный_блок | Вложенный блок FOREACH...GENERATE, используемый с внутренним пакетом. Используйте этот синтаксис: псевдоним = FOREACH вложенный_псевдоним { псевдоним = {вложен_оператор | вложенное_выражение}; [{псевдоним = {вложен_оператор | вложенное_выражение}; …] GENERATE выражение [КАК схема] [выражение [КАК схема]….] }; Где: Вложенный блок заключён в открывающие и закрывающие скобки { … }. Ключевое слово GENERATE должно быть последним оператором вложенного блока. См. Схемы Макросы НЕ разрешены внутри вложенного блока. |
| выражение | Выражение. |
| вложенный_псевдоним | Имя внутреннего пакета. |
| вложен_оператор | Разрешенные операции: CROSS, DISTINCT, FILTER, FOREACH, LIMIT и ORDER BY. Примечание: операторы FOREACH могут быть вложены только до двух уровней. Операторы FOREACH, вложенные на три или более уровней, приведут к ошибке синтаксиса. Вы также можете выполнять проекции внутри вложенного блока. Примеры см. в Примере: Вложенный блок. |
| вложенное_выражение | Любое произвольное поддерживаемое выражение. |
| КАК | Ключевое слово |
| схема | Схема, использующая ключевое слово AS (см. Схемы).
|
Использование
Используйте операцию FOREACH…GENERATE для работы со столбцами данных (если вы хотите работать с кортежами или строками данных, используйте операцию FILTER).
FOREACH...GENERATE работает как с отношениями (внешними пакетами), так и с внутренними пакетами:
-
Если A — отношение (внешний пакет), оператор FOREACH может выглядеть так.
X = FOREACH A GENERATE f1;
-
Если A — внутренний пакет, оператор FOREACH может выглядеть так.
X = FOREACH B { S = FILTER A BY 'xyz'; GENERATE COUNT (S.$0); }
Пример: Проекция
В этом примере звёздочка (*) используется для проекции всех полей из отношения A в отношение X. Отношения A и X идентичны.
X = FOREACH A GENERATE *; DUMP X; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3)
В этом примере два поля из отношения A проецируются для формирования отношения X.
X = FOREACH A GENERATE a1, a2; DUMP X; (1,2) (4,2) (8,3) (4,3) (7,2) (8,4)
Пример: Вложенная проекция
В этом примере, если одно из полей во входном отношении является кортежем, пакетом или картой, мы можем выполнить проекцию на это поле (используя оператор разыменования).
X = FOREACH C GENERATE group, B.b2;
DUMP X;
(1,{(3)})
(4,{(6),(9)})
(8,{(9)})
В этом примере сохраняются несколько вложенных столбцов.
X = FOREACH C GENERATE group, A.(a1, a2);
DUMP X;
(1,{(1,2)})
(4,{(4,2),(4,3)})
(8,{(8,3),(8,4)})
Пример: Схема
В этом примере две поля в отношении A суммируются для формирования отношения X. Определяется схема для проецируемого поля.
X = FOREACH A GENERATE a1+a2 AS f1:int;
DESCRIBE X;
x: {f1: int}
DUMP X;
(3)
(6)
(11)
(7)
(9)
(12)
Y = FILTER X BY f1 > 10;
DUMP Y;
(11)
(12)
Пример: Применение функций
В этом примере встроенная функция SUM() используется для суммирования набора чисел в пакете.
X = FOREACH C GENERATE group, SUM (A.a1); DUMP X; (1,1) (4,8) (8,16)
Пример: Развёртка
В этом примере используется оператор FLATTEN для устранения вложенности.
X = FOREACH C GENERATE group, FLATTEN(A); DUMP X; (1,1,2,3) (4,4,2,1) (4,4,3,3) (8,8,3,4) (8,8,4,3)
Ещё один пример FLATTEN.
X = FOREACH C GENERATE GROUP, FLATTEN(A.a3); DUMP X; (1,3) (4,1) (4,3) (8,4) (8,3)
Ещё один пример FLATTEN. Обратите внимание, что для группы «4» в C в каждом пакете имеются два кортежа. Таким образом, при развёртывании обоих пакетов возвращается декартово произведение этих кортежей; то есть, кортежи (4, 2, 6), (4, 3, 6), (4, 2, 9) и (4, 3, 9).
X = FOREACH C GENERATE FLATTEN(A.(a1, a2)), FLATTEN(B.$1); DUMP X; (1,2,3) (4,2,6) (4,2,9) (4,3,6) (4,3,9) (8,3,9) (8,4,9)
Ещё один пример FLATTEN. Здесь в отношениях A и B есть столбец x. При формировании отношения E необходимо использовать оператор :: для указания, какой столбец x использовать — столбец x отношения A (A::x) или столбец x отношения B (B::x). В этом примере используется столбец x отношения A (A::x).
A = LOAD 'data' AS (x, y); B = LOAD 'data' AS (x, z); C = COGROUP A BY x, B BY x; D = FOREACH C GENERATE flatten(A), flatten(b); E = GROUP D BY A::x; ……
Пример: Вложенный блок
В этом примере вложенный блок выполняет операцию CROSS.
user = load 'user' as (uid, age, gender, region);
session = load 'session' as (uid, region);
C = cogroup user by uid, session by uid;
D = foreach C {
crossed = cross user, session;
generate crossed;
}
dump D;
В этом примере FOREACH вложен до второго уровня.
a = load '1.txt' as (a0, a1:chararray, a2:chararray);
b = group a by a0;
c = foreach b {
c0 = foreach a generate TOMAP(a1,a2);
generate c0;
}
dump c;
В этом примере показаны вложенные операторы CROSS и FOREACH до второго уровня.
a = load '1.txt' as (a0, a1, a2);
b = load '2.txt' as (b0, b1);
c = cogroup a by a0, b by b0;
d = foreach c {
d0 = cross a, b;
d1 = foreach d0 generate a1+b1;
generate d1;
}
dump d;
Предположим, что у нас есть отношения A и B. Обратите внимание, что отношение B содержит внутренний пакет.
A = LOAD 'data' AS (url:chararray,outlink:chararray);
DUMP A;
(www.ccc.com,www.hjk.com)
(www.ddd.com,www.xyz.org)
(www.aaa.com,www.cvn.org)
(www.www.com,www.kpt.net)
(www.www.com,www.xyz.org)
(www.ddd.com,www.xyz.org)
B = GROUP A BY url;
DUMP B;
(www.aaa.com,{(www.aaa.com,www.cvn.org)})
(www.ccc.com,{(www.ccc.com,www.hjk.com)})
(www.ddd.com,{(www.ddd.com,www.xyz.org),(www.ddd.com,www.xyz.org)})
(www.www.com,{(www.www.com,www.kpt.net),(www.www.com,www.xyz.org)})
В этом примере выполняются две разрешённые вложенные операции: FILTER и DISTINCT. Обратите внимание, что последним оператором вложенного блока должно быть GENERATE. Также обратите внимание на использование проекции (PA = FA.outlink;) для извлечения поля. DISTINCT может применяться только к подмножеству полей (а не к отношению) внутри вложенного блока.
X = FOREACH B {
FA= FILTER A BY outlink == 'www.xyz.org';
PA = FA.outlink;
DA = DISTINCT PA;
GENERATE group, COUNT(DA);
}
DUMP X;
(www.aaa.com,0)
(www.ccc.com,0)
(www.ddd.com,1)
(www.www.com,1)
ГРУППИРОВКА
Группирует данные в одном или нескольких отношениях.
Примечание: операторы GROUP и COGROUP идентичны. Оба оператора работают с одним или несколькими отношениями. Для повышения читабельности GROUP используется в операторах, включающих одно отношение, а COGROUP — в операторах, включающих два или более отношений. Вы можете COGROUP до, но не более чем, 127 отношений за один раз.
Синтаксис
| псевдоним = GROUP псевдоним { ALL | BY выражение} [, псевдоним ALL | BY выражение …] [USING 'collected' | 'merge'] [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| псевдоним | Имя отношения. Вы можете COGROUP до, но не более чем, 127 отношений за один раз. |
| ALL | Ключевое слово. Используйте ALL, если вы хотите, чтобы все кортежи попали в одну группу; например, при выполнении агрегаций по всем отношениям. B = GROUP A ALL; |
| BY | Ключевое слово. Используйте этот оператор для группировки отношения по полю, кортежу или выражению. B = GROUP A BY f1; |
| выражение | Выражение кортежа. Это ключ группы или ключевое поле. Если результатом выражения кортежа является одно поле, ключ будет значением первого поля, а не кортежа с одним полем. Для группировки по нескольким ключам заключите ключи в скобки: B = GROUP A BY (key1,key2); |
| USING | Ключевое слово |
| 'collected' | Используйте оператор ‘collected’ с операцией GROUP (работает только с одним отношением). Применяются следующие условия:
Если ваши данные и загрузчики удовлетворяют этим условиям, используйте оператор ‘collected’ для выполнения оптимизированной версии GROUP; операция будет выполняться на стороне карты и избежит выполнения фазы reduce. |
| 'merge' | Используйте оператор ‘merge’ с операцией COGROUP (работает только с двумя или более отношениями). Применяются следующие условия:
Если ваши данные и загрузчики удовлетворяют этим условиям, используйте оператор ‘merge’ для выполнения оптимизированной версии COGROUP; операция будет выполняться на стороне карты и избежит выполнения фазы reduce. |
| PARTITION BY partitioner | Используйте эту функцию для указания Hadoop Partitioner. Partitioner контролирует разбиение ключей промежуточных результатов отображения.
|
| PARALLEL n | Увеличьте параллелизм задания, указав количество задач reduce, n. Дополнительная информация см. в Использование параллельных функций. |
Использование
Оператор GROUP объединяет кортежи, имеющие одинаковый ключ группы (ключевое поле). Ключевое поле будет кортежем, если ключ группы содержит более одного поля, в противном случае он будет иметь тот же тип, что и ключ группы. Результатом операции GROUP является отношение, содержащее один кортеж на группу. Этот кортеж содержит два поля:
-
Первое поле называется «группа» (не путайте с оператором GROUP) и имеет тот же тип, что и ключ группы.
-
Второе поле содержит имя исходного отношения и имеет тип пакет.
-
Имена обоих полей генерируются системой, как показано в примере ниже.
Обратите внимание на следующее относительно операторов GROUP/COGROUP и JOIN:
-
Операторы GROUP и JOIN выполняют похожие функции. GROUP создаёт вложенный набор выходных кортежей, а JOIN — плоский набор выходных кортежей.
-
Операторы GROUP/COGROUP и JOIN обрабатывают нулевые значения по-разному (см. Нулевые значения и операторы GROUP/COGROUP).
Пример
Предположим, у нас есть отношение A.
A = load 'student' AS (name:chararray,age:int,gpa:float);
DESCRIBE A;
A: {name: chararray,age: int,gpa: float}
DUMP A;
(John,18,4.0F)
(Mary,19,3.8F)
(Bill,20,3.9F)
(Joe,18,3.8F)
Теперь предположим, что мы группируем отношение A по полю «возраст», чтобы получить отношение B. Мы можем использовать операторы DESCRIBE и ILLUSTRATE для проверки структуры отношения B. Отношение B имеет два поля. Первое поле называется «группа» и имеет тип int, такой же, как поле «возраст» в отношении A. Второе поле называется «A» после отношения A и имеет тип пакет.
B = GROUP A BY age;
DESCRIBE B;
B: {group: int, A: {name: chararray,age: int,gpa: float}}
ILLUSTRATE B;
etc ...
----------------------------------------------------------------------
| B | group: int | A: bag({name: chararray,age: int,gpa: float}) |
----------------------------------------------------------------------
| | 18 | {(John, 18, 4.0), (Joe, 18, 3.8)} |
| | 20 | {(Bill, 20, 3.9)} |
----------------------------------------------------------------------
DUMP B;
(18,{(John,18,4.0F),(Joe,18,3.8F)})
(19,{(Mary,19,3.8F)})
(20,{(Bill,20,3.9F)})
Далее, как показано в этих операторах FOREACH, мы можем ссылаться на поля в отношении B по именам «группа» и «A» или по позиционной нотации.
C = FOREACH B GENERATE group, COUNT(A);
DUMP C;
(18,2L)
(19,1L)
(20,1L)
C = FOREACH B GENERATE $0, $1.name;
DUMP C;
(18,{(John),(Joe)})
(19,{(Mary)})
(20,{(Bill)})
Пример
Предположим, у нас есть отношение A.
A = LOAD 'data' as (f1:chararray, f2:int, f3:int); DUMP A; (r1,1,2) (r2,2,1) (r3,2,8) (r4,4,4)
В этом примере кортежи сгруппированы с помощью выражения, f2*f3.
X = GROUP A BY f2*f3;
DUMP X;
(2,{(r1,1,2),(r2,2,1)})
(16,{(r3,2,8),(r4,4,4)})
Пример
Предположим, у нас есть две реляции, A и B.
A = LOAD 'data1' AS (owner:chararray,pet:chararray); DUMP A; (Alice,turtle) (Alice,goldfish) (Alice,cat) (Bob,dog) (Bob,cat) B = LOAD 'data2' AS (friend1:chararray,friend2:chararray); DUMP B; (Cindy,Alice) (Mark,Alice) (Paul,Bob) (Paul,Jane)
В этом примере кортежи объединяются с помощью поля «owner» из реляции A и поля «friend2» из реляции B в качестве ключевых полей. Оператор DESCRIBE показывает схему для реляции X, которая имеет три поля, «group», «A» и «B» (см. оператор GROUP для получения информации о названиях полей).
X = COGROUP A BY owner, B BY friend2;
DESCRIBE X;
X: {group: chararray,A: {owner: chararray,pet: chararray},B: {friend1: chararray,friend2: chararray}}
Реляция X выглядит следующим образом. Кортеж создается для каждого уникального ключевого поля. Кортеж включает ключевое поле и два мешка. Первый мешок содержит кортежи из первой реляции с соответствующим ключевым полем. Второй мешок содержит кортежи из второй реляции с соответствующим ключевым полем. Если кортежи не соответствуют ключевому полю, мешок пуст.
(Alice,{(Alice,turtle),(Alice,goldfish),(Alice,cat)},{(Cindy,Alice),(Mark,Alice)})
(Bob,{(Bob,dog),(Bob,cat)},{(Paul,Bob)})
(Jane,{},{(Paul,Jane)})
Пример
Этот пример демонстрирует группировку по нескольким ключам.
A = LOAD 'allresults' USING PigStorage() AS (tcid:int, tpid:int, date:chararray, result:chararray, tsid:int, tag:chararray); B = GROUP A BY (tcid, tpid);
Пример: PARTITION BY
Для использования Hadoop Partitioner добавьте предложение PARTITION BY к соответствующему оператору:
A = LOAD 'input_data'; B = GROUP A BY $0 PARTITION BY org.apache.pig.test.utils.SimpleCustomPartitioner PARALLEL 2;
Вот код для SimpleCustomPartitioner:
public class SimpleCustomPartitioner extends Partitioner <PigNullableWritable, Writable> {
//@Override
public int getPartition(PigNullableWritable key, Writable value, int numPartitions) {
if(key.getValueAsPigType() instanceof Integer) {
int ret = (((Integer)key.getValueAsPigType()).intValue() % numPartitions);
return ret;
}
else {
return (key.hashCode()) % numPartitions;
}
}
}
IMPORT
См. IMPORT (макросы)
JOIN (внутреннее)
Выполняет внутреннее соединение двух или более реляций на основе общих значений полей.
Синтаксис
| alias = JOIN alias BY {expression|'('expression [, expression …]')'} (, alias BY {expression|'('expression [, expression …]')'} …) [USING 'replicated' | 'skewed' | 'merge' | 'merge-sparse'] [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя реляции. |
| BY | Ключевое слово |
| expression | Выражение поля. Пример: X = JOIN A BY fieldA, B BY fieldB, C BY fieldC; |
| USING | Ключевое слово |
| 'replicated' | Используется для выполнения реплицированных соединений (см. Реплицированные соединения). |
| 'skewed' | Используется для выполнения соединений со смещенными данными (см. Соединения со смещенными данными). |
| 'merge' | Используется для выполнения соединений слиянием (см. Соединения слиянием). |
| 'merge-sparse' | Используется для выполнения соединений слиянием с разреженными данными (см. Соединения слиянием с разреженными данными). |
| PARTITION BY partitioner | Используйте эту функцию для указания Hadoop Partitioner. Partitioner управляет разбиением ключей промежуточных результатов map-вычислений.
Эта функция НЕ может использоваться с соединениями со смещенными данными. |
| PARALLEL n | Увеличьте параллельность задания, указав количество задач reduce, n. Дополнительная информация в разделе Использование параллельных функций. |
Использование
Используйте оператор JOIN для выполнения внутреннего, равносогласованного соединения двух или более реляций на основе общих значений полей. Внутренние соединения игнорируют нулевые ключи, поэтому имеет смысл отфильтровать их перед соединением.
Обратите внимание на следующее в отношении операторов GROUP/COGROUP и JOIN:
-
Операторы GROUP и JOIN выполняют похожие функции. GROUP создает вложенный набор выходных кортежей, в то время как JOIN создает плоский набор выходных кортежей.
-
Операторы GROUP/COGROUP и JOIN обрабатывают нулевые значения по-разному (см. Нули и оператор JOIN).
Самосоединение
Для выполнения самосоединений в Pig загрузите одни и те же данные несколько раз под разными псевдонимами, чтобы избежать конфликтов имен.
В этом примере те же данные загружаются дважды с псевдонимами A и B.
grunt> A = load 'mydata'; grunt> B = load 'mydata'; grunt> C = join A by $0, B by $0; grunt> explain C;
Пример
Предположим, у нас есть реляции A и B.
A = LOAD 'data1' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3) B = LOAD 'data2' AS (b1:int,b2:int); DUMP B; (2,4) (8,9) (1,3) (2,7) (2,9) (4,6) (4,9)
В этом примере реляции A и B соединяются по их первым полям.
X = JOIN A BY a1, B BY b1; DUMP X; (1,2,3,1,3) (4,2,1,4,6) (4,3,3,4,6) (4,2,1,4,9) (4,3,3,4,9) (8,3,4,8,9) (8,4,3,8,9)
JOIN (внешнее)
Выполняет внешнее соединение двух реляций на основе общих значений полей.
Синтаксис
| alias = JOIN left-alias BY left-alias-column [LEFT|RIGHT|FULL] [OUTER], right-alias BY right-alias-column [USING 'replicated' | 'skewed' | 'merge'] [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя реляции. Применяется к alias, left-alias и right-alias. |
| alias-column | Имя столбца соединения для соответствующей реляции. Применяется к left-alias-column и right-alias-column. |
| BY | Ключевое слово |
| LEFT | Левое внешнее соединение. |
| RIGHT | Правое внешнее соединение. |
| FULL | Полное внешнее соединение. |
| OUTER | (Необязательно) Ключевое слово |
| USING | Ключевое слово |
| 'replicated' | Используется для выполнения реплицированных соединений (см. Реплицированные соединения). Только левое внешнее соединение поддерживается для реплицированных соединений. |
| 'skewed' | Используется для выполнения соединений со смещенными данными (см. Соединения со смещенными данными). |
| 'merge' | Используется для выполнения соединений слиянием (см. Соединения слиянием). |
| PARTITION BY partitioner | Используйте эту функцию для указания Hadoop Partitioner. Partitioner управляет разбиением ключей промежуточных результатов map-вычислений.
Эта функция НЕ может использоваться с соединениями со смещенными данными. |
| PARALLEL n | Увеличьте параллельность задания, указав количество задач reduce, n. Дополнительная информация в разделе Использование параллельных функций. |
Использование
Используйте оператор JOIN с соответствующими ключевыми словами для выполнения левых, правых или полных внешних соединений. Ключевое слово OUTER является необязательным для внешних соединений; ключевые слова LEFT, RIGHT и FULL подразумевают левое внешнее, правое внешнее и полное внешнее соединение соответственно, когда OUTER опущено. Синтаксис Pig Latin тесно придерживается стандарта SQL.
Обратите внимание на следующее:
-
Внешние соединения будут работать только в том случае, если реляции, которым необходимо генерировать null-значения (в случае несовпадающих ключей), имеют схемы.
-
Внешние соединения будут работать только для двусторонних соединений; для выполнения многостороннего внешнего соединения потребуется выполнить несколько двусторонних операторов внешнего соединения.
Примеры
В этом примере показано левое внешнее соединение.
A = LOAD 'a.txt' AS (n:chararray, a:int); B = LOAD 'b.txt' AS (n:chararray, m:chararray); C = JOIN A by $0 LEFT OUTER, B BY $0;
В этом примере показано полное внешнее соединение.
A = LOAD 'a.txt' AS (n:chararray, a:int); B = LOAD 'b.txt' AS (n:chararray, m:chararray); C = JOIN A BY $0 FULL, B BY $0;
В этом примере показано реплицированное левое внешнее соединение.
A = LOAD 'large'; B = LOAD 'tiny'; C= JOIN A BY $0 LEFT, B BY $0 USING 'replicated';
В этом примере показано смещенное полное внешнее соединение.
A = LOAD 'studenttab' as (name, age, gpa); B = LOAD 'votertab' as (name, age, registration, contribution); C = JOIN A BY name FULL, B BY name USING 'skewed';
LIMIT
Ограничивает количество выходных кортежей.
Синтаксис
| alias = LIMIT alias n; |
Термины
| alias | Имя реляции. |
| n | Количество выходных кортежей, либо:
Примечание: выражение может состоять из констант или скаляров; оно не может содержать столбцы из входной реляции. Примечание: Использование скаляра вместо константы в LIMIT автоматически отключает большинство оптимизаций (выполняется только push-before-foreach). |
Использование
Используйте оператор LIMIT для ограничения количества выходных кортежей.
Если указанное количество выходных кортежей равно или превышает количество кортежей в реляции, возвращаются все кортежи из реляции.
Если указанное количество выходных кортежей меньше количества кортежей в реляции, возвращаются n кортежей. Нет гарантии, какие n кортежей будут возвращены, и возвращаемые кортежи могут меняться от одного запуска к другому. Определенный набор кортежей можно запросить с помощью оператора ORDER, за которым следует оператор LIMIT.
Примечание: оператор LIMIT позволяет Pig избежать обработки всех кортежей в реляции. В большинстве случаев запрос, использующий LIMIT, будет выполняться эффективнее, чем идентичный запрос без LIMIT. Всегда рекомендуется использовать LIMIT, если это возможно.
Примеры
В этом примере предел выражен как скаляр.
a = load 'a.txt'; b = group a all; c = foreach b generate COUNT(a) as sum; d = order a by $0; e = limit d c.sum/100;
Предположим, у нас есть реляция A.
A = LOAD 'data' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3)
В этом примере вывод ограничен тремя кортежами. Обратите внимание, что нет гарантии, какие именно три кортежа будут выведены.
X = LIMIT A 3; DUMP X; (1,2,3) (4,3,3) (7,2,5)
В этом примере оператор ORDER используется для упорядочивания кортежей, а оператор LIMIT используется для вывода первых трех кортежей.
B = ORDER A BY f1 DESC, f2 ASC; DUMP B; (8,3,4) (8,4,3) (7,2,5) (4,2,1) (4,3,3) (1,2,3) X = LIMIT B 3; DUMP X; (8,3,4) (8,4,3) (7,2,5)
LOAD
Загружает данные из файловой системы.
Синтаксис
| LOAD 'data' [USING function] [AS schema]; |
Термины
| 'data' | Имя файла или каталога в одинарных кавычках. Если указано имя каталога, загружаются все файлы в этом каталоге. Можно использовать Hadoop globbing для указания файлов на уровне файла или каталога (см. Hadoop globStatus для получения подробной информации о синтаксисе globbing). Примечание: Pig использует Hadoop globbing, поэтому функциональность ИДЕНТИЧНА. Однако, при выполнении из командной строки с помощью команды Hadoop fs (а не оператора Pig LOAD), оболочка Unix может выполнить некоторые подстановки; это может изменить результат, создав впечатление, что globbing работает по-разному для Pig и Hadoop. Например:
|
| USING | Ключевое слово. Если опущен оператор USING, используется функция по умолчанию PigStorage. |
| function | Функция загрузки.
|
| AS | Ключевое слово. |
| schema | Схема, использующая ключевое слово AS, заключённая в скобки (см. Схемы). Загрузчик создает данные указанного типом схемы. Если данные не соответствуют схеме, в зависимости от загрузчика, генерируется либо значение null, либо ошибка. Примечание: для повышения производительности загрузчик может не сразу преобразовать данные в указанный формат; однако вы можете выполнять операции над данными, предполагая указанный тип. |
Использование
Используйте оператор LOAD для загрузки данных из файловой системы.
Примеры
Предположим, что у нас есть файл данных, называемый myfile.txt. Поля разделены табуляцией. Записи разделены символами новой строки.
1 2 3 4 2 1 8 3 4
В этом примере функция загрузки по умолчанию PigStorage загружает данные из myfile.txt, чтобы сформировать отношение A. Два оператора LOAD эквивалентны. Обратите внимание, что, поскольку схема не указана, поля не имеют имён, а все поля по умолчанию имеют тип bytearray.
A = LOAD 'myfile.txt';
A = LOAD 'myfile.txt' USING PigStorage('\t');
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
В этом примере схема указана с помощью ключевого слова AS. Два оператора LOAD эквивалентны. Можно использовать операторы DESCRIBE и ILLUSTRATE для просмотра схемы.
A = LOAD 'myfile.txt' AS (f1:int, f2:int, f3:int);
A = LOAD 'myfile.txt' USING PigStorage('\t') AS (f1:int, f2:int, f3:int);
DESCRIBE A;
a: {f1: int,f2: int,f3: int}
ILLUSTRATE A;
---------------------------------------------------------
| a | f1: bytearray | f2: bytearray | f3: bytearray |
---------------------------------------------------------
| | 4 | 2 | 1 |
---------------------------------------------------------
---------------------------------------
| a | f1: int | f2: int | f3: int |
---------------------------------------
| | 4 | 2 | 1 |
---------------------------------------
Примеры того, как указать более сложные схемы для использования с оператором LOAD, см. в разделах Схемы для сложных типов данных и Схемы для нескольких типов.
MAPREDUCE
Выполняет собственные задания MapReduce внутри скрипта Pig.
Синтаксис
| alias1 = MAPREDUCE 'mr.jar' STORE alias2 INTO 'inputLocation' USING storeFunc LOAD 'outputLocation' USING loadFunc AS schema [`params, ... `]; |
Термины
| alias1, alias2 | Имена отношений. |
| mr.jar | Файл JAR MapReduce (в одинарных кавычках). Можно указать любой файл JAR MapReduce, который можно запустить с помощью команды hadoop jar mymr.jar params. Значения для inputLocation и outputLocation могут быть переданы в params. |
| STORE ... INTO ... USING | См. STORE Сохранить alias2 в inputLocation с использованием storeFunc, который затем используется заданием MapReduce для чтения данных. |
| LOAD ... USING ... AS | См. LOAD После выполнения задания MapReduce mr.jar загрузить данные из outputLocation в alias1 с использованием loadFunc в качестве схемы. |
| `params, ...` | Дополнительные параметры, необходимые для задания MapReduce (в обратных кавычках). |
Использование
Используйте оператор MAPREDUCE для запуска собственных заданий MapReduce изнутри скрипта Pig.
Пути ввода и вывода для программы MapReduce передаются Pig с помощью операторов STORE/LOAD. Однако Pig не передает эту информацию (и не требует ее передачи) программе MapReduce. Если вы хотите передать пути ввода и вывода программе MapReduce, вы можете использовать оператор params или закодировать пути в программе MapReduce.
Пример
Этот пример демонстрирует, как запустить программу MapReduce wordcount из Pig. Обратите внимание, что файлы, указанные как пути ввода и вывода в операторе MAPREDUCE, НЕ будут автоматически удалены Pig. Вам потребуется удалить их вручную.
A = LOAD 'WordcountInput.txt';
B = MAPREDUCE 'wordcount.jar' STORE A INTO 'inputDir' LOAD 'outputDir'
AS (word:chararray, count: int) `org.myorg.WordCount inputDir outputDir`;
ORDER BY
Сортирует отношение по одному или нескольким полям.
Синтаксис
| alias = ORDER alias BY { * [ASC|DESC] | field_alias [ASC|DESC] [, field_alias [ASC|DESC] …] } [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| * | Обозначение кортежа. |
| field_alias | Поле в отношении. Поле должно быть простого типа. |
| ASC | Сортировать по возрастанию. |
| DESC | Сортировать по убыванию. |
| PARALLEL n | Увеличить параллелизм задания, указав количество задач reduce, n. Для получения дополнительной информации см. Использование функций параллелизма. |
Использование
Примечание: ORDER BY НЕ устойчив; если несколько записей имеют одинаковый ключ ORDER BY, порядок, в котором возвращаются эти записи, не определён и не гарантируется, что он будет одинаковым при каждом запуске.
В Pig отношения неупорядочены (см. Отношения, множества, кортежи, поля):
-
Если вы отсортируете отношение A, чтобы получить отношение X (X = ORDER A BY * DESC;), отношения A и X всё равно содержат одни и те же данные.
-
Если вы получите отношение X (DUMP X;), данные будут гарантированно в указанном порядке (по убыванию).
-
Однако, если вы дополнительно обработаете отношение X (Y = FILTER X BY $0 > 1;), нет гарантии, что данные будут обработаны в первоначально указанном порядке (по убыванию).
Pig в настоящее время поддерживает сортировку по полям с простыми типами или по кортежу (*). Нельзя сортировать по полям со сложными типами или выражениями.
A = LOAD 'mydata' AS (x: int, y: map[]); B = ORDER A BY x; -- this is allowed because x is a simple type B = ORDER A BY y; -- this is not allowed because y is a complex type B = ORDER A BY y#'id'; -- this is not allowed because y#'id' is an expression
Примеры
Предположим, что у нас есть отношение A.
A = LOAD 'data' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) (8,3,4) (4,3,3) (7,2,5) (8,4,3)
В этом примере отношение A сортируется по третьему полю, f3, по убыванию. Обратите внимание, что порядок трёх кортежей, заканчивающихся на 3, может изменяться.
X = ORDER A BY a3 DESC; DUMP X; (7,2,5) (8,3,4) (1,2,3) (4,3,3) (8,4,3) (4,2,1)
RANK
Возвращает каждый кортеж с рангом в отношении.
Синтаксис
| alias = RANK alias [ BY { * [ASC|DESC] | field_alias [ASC|DESC] [, field_alias [ASC|DESC] …] } [DENSE] ]; |
Термины
| alias | Имя отношения. |
| * | Обозначение кортежа. |
| field_alias | Поле в отношении. Поле должно быть простого типа. |
| ASC | Сортировать по возрастанию. |
| DESC | Сортировать по убыванию. |
| DENSE | Без разрывов в значениях ранжирования. |
Использование
При указании без сортировки по полю оператор RANK просто добавляет последовательное значение к каждому кортежу.
В противном случае, оператор RANK использует каждое поле (или набор полей) для сортировки отношения. Ранг кортежа равен единице плюс количеству различных значений ранга, предшествующих ему. Если два или более кортежей имеют одинаковые значения сортирующих полей, они получат одинаковый ранг.
ПРИМЕЧАНИЕ: При использовании опции DENSE, совпадения не вызывают разрывов в значениях ранжирования.
Примеры
Предположим, что у нас есть отношение A.
A = load 'data' AS (f1:chararray,f2:int,f3:chararray);
DUMP A;
(David,1,N)
(Tete,2,N)
(Ranjit,3,M)
(Ranjit,3,P)
(David,4,Q)
(David,4,Q)
(Jillian,8,Q)
(JaePak,7,Q)
(Michael,8,T)
(Jillian,8,Q)
(Jose,10,V)
В этом примере оператор RANK не изменяет порядок отношения и просто добавляет к каждому кортежу последовательное значение.
B = rank A;
dump B;
(1,David,1,N)
(2,Tete,2,N)
(3,Ranjit,3,M)
(4,Ranjit,3,P)
(5,David,4,Q)
(6,David,4,Q)
(7,Jillian,8,Q)
(8,JaePak,7,Q)
(9,Michael,8,T)
(10,Jillian,8,Q)
(11,Jose,10,V)
В этом примере оператор RANK работает с полями f1 и f2 и с различными порядками сортировки. RANK сортирует отношение по этим полям и добавляет значение ранга к каждому кортежу. В противном случае оператор RANK использует каждое поле (или набор полей) для сортировки отношения. Ранг кортежа равен единице плюс количеству различных значений ранга, предшествующих ему. Если два или более кортежей имеют одинаковые значения сортирующих полей, они получат одинаковый ранг.
C = rank A by f1 DESC, f2 ASC;
dump C;
(1,Tete,2,N)
(2,Ranjit,3,M)
(2,Ranjit,3,P)
(4,Michael,8,T)
(5,Jose,10,V)
(6,Jillian,8,Q)
(6,Jillian,8,Q)
(8,JaePak,7,Q)
(9,David,1,N)
(10,David,4,Q)
(10,David,4,Q)
Тот же пример, что и раньше, но DENSE. В этом случае нет пробелов в значениях ранжирования.
C = rank A by f1 DESC, f2 ASC DENSE;
dump C;
(1,Tete,2,N)
(2,Ranjit,3,M)
(2,Ranjit,3,P)
(3,Michael,8,T)
(4,Jose,10,V)
(5,Jillian,8,Q)
(5,Jillian,8,Q)
(6,JaePak,7,Q)
(7,David,1,N)
(8,David,4,Q)
(8,David,4,Q)
SAMPLE
Выбирает случайную выборку данных на основе заданного размера выборки.
Синтаксис
| SAMPLE alias size; |
Термины
| псевдоним | Название отношения. |
| размер | Размер выборки, либо
Примечание: выражение может состоять из констант или скаляров; оно не может содержать столбцов из входного отношения. |
Использование
Используйте оператор SAMPLE для выбора случайной выборки данных с указанным размером выборки. SAMPLE — это вероятностный оператор; нет гарантии, что для определенного размера выборки каждый раз при использовании оператора будет возвращено ровно такое же количество кортежей.
Пример
В этом примере отношение X будет содержать 1% данных в отношении A.
A = LOAD 'data' AS (f1:int,f2:int,f3:int); X = SAMPLE A 0.01;
В этом примере используется скалярное выражение (оно будет выбирать примерно 1000 записей из входных данных).
a = load 'a.txt'; b = group a all; c = foreach b generate COUNT(a) as num_rows; e = sample a 1000/c.num_rows;
SPLIT
Разделяет отношение на два или более отношений.
Синтаксис
| SPLIT псевдоним INTO псевдоним IF выражение, псевдоним IF выражение [, псевдоним IF выражение …] [, псевдоним OTHERWISE]; |
Термины
| псевдоним | Название отношения. |
| INTO | Обязательное ключевое слово. |
| IF | Обязательное ключевое слово. |
| выражение | Выражение. |
| OTHERWISE | Необязательное ключевое слово. Обозначает отношение по умолчанию. |
Использование
Используйте оператор SPLIT для разделения содержимого отношения на два или более отношений на основе некоторого выражения. В зависимости от условий, указанных в выражении:
-
Один кортеж может быть назначен более чем одному отношению.
-
Один кортеж может не быть назначен ни одному отношению.
Пример
В этом примере отношение A разделяется на три отношения: X, Y и Z.
A = LOAD 'data' AS (f1:int,f2:int,f3:int); DUMP A; (1,2,3) (4,5,6) (7,8,9) SPLIT A INTO X IF f1<7, Y IF f2==5, Z IF (f3<6 OR f3>6); DUMP X; (1,2,3) (4,5,6) DUMP Y; (4,5,6) DUMP Z; (1,2,3) (7,8,9)
Пример
В этом примере операторы SPLIT и FILTER по существу эквивалентны. Однако, поскольку SPLIT реализован как «разделение потока данных, а затем применение фильтров», оператор SPLIT более затратный, чем оператор FILTER, поскольку Pig должен отфильтровать и сохранить два потока данных.
SPLIT input_var INTO output_var IF (field1 is not null), ignored_var IF (field1 is null); -- where ignored_var is not used elsewhere output_var = FILTER input_var BY (field1 is not null);
STORE
Сохраняет результаты в файловой системе.
Синтаксис
| STORE псевдоним INTO 'директория' [USING функция]; |
Термины
| псевдоним | Название отношения. |
| INTO | Обязательное ключевое слово. |
| 'директория' | Имя каталога хранения в кавычках. Если каталог уже существует, операция STORE завершится неудачей. Выходные файлы данных с именами part-nnnnn записываются в этот каталог. |
| USING | Ключевое слово. Используйте этот пункт, чтобы назвать функцию хранения. Если опустить пункт USING, используется функция хранения PigStorage по умолчанию. |
| функция | Функция хранения.
|
Использование
Используйте оператор STORE для выполнения (выполнения) операторов Pig Latin и сохранения (сохранения) результатов в файловой системе. Используйте STORE для производственных скриптов и обработки в пакетном режиме.
Примечание: для отладки скриптов во время разработки вы можете использовать DUMP для проверки промежуточных результатов.
Примеры
В этом примере данные сохраняются с помощью PigStorage и символа звездочка (*) в качестве разделителя полей.
A = LOAD 'data' AS (a1:int,a2:int,a3:int);
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
(7,2,5)
(8,4,3)
STORE A INTO 'myoutput' USING PigStorage ('*');
CAT myoutput;
1*2*3
4*2*1
8*3*4
4*3*3
7*2*5
8*4*3
В этом примере для форматирования данных перед сохранением используется функция CONCAT.
A = LOAD 'data' AS (a1:int,a2:int,a3:int);
DUMP A;
(1,2,3)
(4,2,1)
(8,3,4)
(4,3,3)
(7,2,5)
(8,4,3)
B = FOREACH A GENERATE CONCAT('a:',(chararray)f1), CONCAT('b:',(chararray)f2), CONCAT('c:',(chararray)f3);
DUMP B;
(a:1,b:2,c:3)
(a:4,b:2,c:1)
(a:8,b:3,c:4)
(a:4,b:3,c:3)
(a:7,b:2,c:5)
(a:8,b:4,c:3)
STORE B INTO 'myoutput' using PigStorage(',');
CAT myoutput;
a:1,b:2,c:3
a:4,b:2,c:1
a:8,b:3,c:4
a:4,b:3,c:3
a:7,b:2,c:5
a:8,b:4,c:3
STREAM
Отправляет данные во внешнюю скрипт или программу.
Синтаксис
| псевдоним = STREAM псевдоним [, псевдоним …] THROUGH {`команда` | cmd_псевдоним } [AS схема] ; |
Термины
| псевдоним | Название отношения. |
| THROUGH | Ключевое слово. |
| `команда` | Команда, включая аргументы, заключенная в обратные кавычки (где команда — это все, что может быть выполнено). |
| cmd_псевдоним | Имя команды, созданной с помощью оператора DEFINE (см. DEFINE (UDFs, streaming) для дополнительных примеров потоковой передачи). |
| AS | Ключевое слово. |
| схема | Схема с использованием ключевого слова AS, заключенная в скобки (см. Схемы). |
Использование
Используйте оператор STREAM для отправки данных через внешнюю скрипт или программу. Несколько операторов stream могут появляться в одном скрипте Pig. Операторы stream могут быть расположены рядом друг с другом или между ними могут быть другие операции.
При использовании с командой оператор stream может выглядеть так:
A = LOAD 'data'; B = STREAM A THROUGH `stream.pl -n 5`;
При использовании с cmd_псевдонимом оператор stream может выглядеть так, где mycmd — это определенный псевдоним.
A = LOAD 'data'; DEFINE mycmd `stream.pl –n 5`; B = STREAM A THROUGH mycmd;
О гарантиях данных
Гарантии данных определяются на основе расположения оператора потоковой передачи в скрипте Pig.
-
Неупорядоченные данные — нет гарантии порядка, в котором данные будут переданы в приложение потоковой передачи.
-
Сгруппированные данные — данные для одного и того же сгруппированного ключа гарантированно будут предоставлены приложению потоковой передачи непрерывно.
-
Сгруппированные и упорядоченные данные — данные для одного и того же сгруппированного ключа гарантированно будут предоставлены приложению потоковой передачи непрерывно. Кроме того, данные внутри группы гарантированно будут отсортированы по указанному вторичному ключу.
Помимо расположения, группировка и упорядочение данных могут определяться самими данными. Однако вам необходимо знать свойства данных, чтобы иметь возможность воспользоваться их структурой.
Пример: Гарантии данных
В этом примере данные неупорядочены.
A = LOAD 'data'; B = STREAM A THROUGH `stream.pl`;
В этом примере данные сгруппированы.
A = LOAD 'data'; B = GROUP A BY $1; C = FOREACH B FLATTEN(A); D = STREAM C THROUGH `stream.pl`;
В этом примере данные сгруппированы и упорядочены.
A = LOAD 'data';
B = GROUP A BY $1;
C = FOREACH B {
D = ORDER A BY ($3, $4);
GENERATE D;
}
E = STREAM C THROUGH `stream.pl`;
Пример: Схемы
В этом примере схема указана как часть оператора STREAM.
X = STREAM A THROUGH `stream.pl` as (f1:int, f2:int, f3:int);
UNION
Вычисляет объединение двух или более отношений.
Синтаксис
| псевдоним = UNION [ONSCHEMA] псевдоним, псевдоним [, псевдоним …]; |
Термины
| псевдоним | Название отношения. |
| ONSCHEMA | Используйте пункт ONSCHEMA для задания объединения по именованным полям (а не по позиционному обозначению). Все входные данные для объединения должны иметь не-неизвестную (не-NULL) схему. |
Использование
Используйте оператор UNION для объединения содержимого двух или более отношений. Оператор UNION:
-
Не сохраняет порядок кортежей. Как входное, так и выходное отношения интерпретируются как неупорядоченные мешки кортежей.
-
Не гарантирует (как базы данных), что все кортежи соответствуют одной схеме или что они имеют одинаковое количество полей. Однако в типичной ситуации это должно быть так; поэтому ответственность пользователя заключается в том, чтобы либо (1) гарантировать, что кортежи во входных отношениях имеют одинаковую схему, либо (2) иметь возможность обрабатывать различные кортежи в выходном отношении.
-
Не исключает повторяющиеся кортежи.
Поведение схем
Поведение схем для UNION (позиционное обозначение/типы данных) и UNION ONSCHEMA (именованные поля/типы данных) одинаково, за исключением случаев, когда указано иное.
Объединение отношений с двумя разными размерами приводит к схеме с значением null (только объединение):
A: (a1:long, a2:long) B: (b1:long, b2:long, b3:long) A union B: null
Объединение столбцов с несовместимыми типами приводит к типу bytearray:
A: (a1:long, a2:long) B: (b1:(b11:long, b12:long), b2:long) A union B: (a1:bytearray, a2:long)
Объединение столбцов совместимого типа приведет к типу "escalate". Приоритет:
- double > float > long > int > bytearray
- tuple|bag|map|chararray > bytearray
A: (a1:int, a2:bytearray, a3:int) B: (b1:float, b2:chararray, b3:bytearray) A union B: (a1:float, a2:chararray, a3:int)
Объединение различных внутренних типов приводит к пустому сложному типу:
A: (a1:(a11:long, a12:int), a2:{(a21:charray, a22:int)})
B: (b1:(b11:int, b12:int), b2:{(b21:int, b22:int)})
A union B: (a1:(), a2:{()})
Псевдоним первого отношения всегда используется как псевдоним поля объединенного отношения.
Пример
В этом примере вычисляется объединение отношения A и B.
A = LOAD 'data' AS (a1:int,a2:int,a3:int); DUMP A; (1,2,3) (4,2,1) B = LOAD 'data' AS (b1:int,b2:int); DUMP A; (2,4) (8,9) (1,3) X = UNION A, B; DUMP X; (1,2,3) (4,2,1) (2,4) (8,9) (1,3)
Пример
В этом примере показано использование ONSCHEMA.
L1 = LOAD 'f1' USING (a : int, b : float);
DUMP L1;
(11,12.0)
(21,22.0)
L2 = LOAD 'f1' USING (a : long, c : chararray);
DUMP L2;
(11,a)
(12,b)
(13,c)
U = UNION ONSCHEMA L1, L2;
DESCRIBE U ;
U : {a : long, b : float, c : chararray}
DUMP U;
(11,12.0,)
(21,22.0,)
(11,,a)
(12,,b)
(13,,c)
Управляющие операторы UDF
ОПРЕДЕЛЕНИЕ (UDF, потоковое)
Присваивает псевдоним UDF или потоковой команде.
Синтаксис: UDF и потоковая обработка
| ОПРЕДЕЛИТЬ псевдоним {функция | [`команда` [вход] [выход] [пересылка] [кеш] [stderr] ] }; |
Термины
| псевдоним | Имя функции UDF или имя потоковой команды (cmd_alias для оператора ПОТОК). |
| функция | Для использования с функциями. Имя функции UDF. |
| `команда` | Для использования с потоковой обработкой. Команда, включая аргументы, заключённые в обратные кавычки (где команда — всё, что может быть выполнено). Описания пунктов (вход, выход, пересылка, кеш, stderr) приведены ниже. Обратите внимание на следующее:
|
| вход | Для использования с потоковой обработкой. ВХОД ({stdin | 'путь'} [Используя сериализатор] [, {stdin | 'путь'} [Используя сериализатор] …]) Где:
|
| выход | Для использования с потоковой обработкой. ВЫХОД ({stdout | stderr | 'путь'} [Используя десериализатор] [, {stdout | stderr | 'путь'} [Используя десериализатор] …]) Где:
|
| пересылка | Для использования с потоковой обработкой. ПЕРЕСЫЛАТЬ('путь' [, 'путь' …]) Где:
|
| кеш | Для использования с потоковой обработкой. КЭШИРОВАТЬ('путь_dfs#имя_файла' [, 'путь_dfs#имя_файла' …]) Где:
|
| stderr | Для использования с потоковой обработкой. STDERR( '/каталог') или STDERR( '/каталог' ОГРАНИЧЕНИЕ n) Где:
|
Использование
Используйте оператор ОПРЕДЕЛИТЬ для присвоения имени (псевдонима) функции UDF или потоковой команде.
Используйте ОПРЕДЕЛИТЬ для указания функции UDF, когда:
-
Функция имеет длинное имя пакета, которое вы не хотите включать в скрипт, особенно если вы вызываете функцию несколько раз в этом скрипте.
-
Конструктор функции принимает строковые параметры. Если вам нужно использовать различные параметры конструктора для разных вызовов функции, вам потребуется создать несколько определений — по одному для каждого набора параметров.
Используйте ОПРЕДЕЛИТЬ для указания потоковой команды, когда:
-
Описание потоковой команды сложное.
-
Описание потоковой команды требует дополнительных параметров (вход, выход и т. д.).
Об входных и выходных данных
Для преобразования данных из кортежей в формат, который может обрабатываться потоковым приложением, требуется сериализация. Для преобразования выходных данных потокового приложения обратно в кортежи требуется десериализация. PigStreaming является функцией сериализации/десериализации по умолчанию.
Потоковая обработка использует тот же формат по умолчанию, что и PigStorage, для сериализации/десериализации данных. Если вы хотите явно указать формат, вы можете сделать это, как показано ниже (см. дополнительные примеры в разделе Примеры: Вход/Выход).
DEFINE CMD `perl PigStreaming.pl - nameMap` input(stdin using PigStreaming(',')) output(stdout using PigStreaming(','));
A = LOAD 'file';
B = STREAM B THROUGH CMD;
Если вам нужен другой формат, вам потребуется создать пользовательские функции сериализации/десериализации, реализовав соответствующие интерфейсы.
interface PigToStream {
/**
* Given a tuple, produce an array of bytes to be passed to the streaming
* executable.
*/
public byte[] serialize(Tuple t) throws IOException;
}
interface StreamToPig {
/**
* Given a byte array from a streaming executable, produce a tuple.
*/
public Tuple deserialize(byte[]) throws IOException;
/**
* This will be called on the front end during planning and not on the back
* end during execution.
*
* @return the {@link LoadCaster} associated with this object.
* @throws IOException if there is an exception during LoadCaster
*/
public LoadCaster getLoadCaster() throws IOException;
}
О пересылке
Используйте параметр пересылка, чтобы отправлять двоичные файлы потоковой обработки и вспомогательные файлы (если таковые имеются) с узла клиента на узлы вычислений. Pig не автоматически пересылает зависимости; вы сами должны явно указывать все зависимости и убедиться, что программное обеспечение, на котором основана обработка (например, perl или python), установлено на кластере. Вспомогательные файлы пересылаются в текущую рабочую директорию задачи, и следует указывать только относительные пути. Любые предварительно установленные двоичные файлы должны быть указаны в переменной PATH.
С помощью параметра пересылка можно указывать только файлы, а не каталоги. Одним из способов решения этой проблемы является архивирование всех зависимостей в архивный файл, который точно отражает необходимую структуру на узлах вычислений, а затем создание оболочки для вашего скрипта, которая будет распаковывать зависимости перед выполнением.
Обратите внимание, что параметр пересылка имеет две составляющие: спецификация источника, указанная в пункте пересылка( ), является представлением вашей машины; спецификация команды является представлением фактического кластера. Единственная гарантия состоит в том, что пересылаемые файлы доступны в текущей рабочей директории запущенной задачи и что ваша текущая рабочая директория также находится в переменной окружения PATH.
Пересылка файлов по относительным или абсолютным путям не поддерживается, поскольку у вас может не быть разрешения на чтение/запись/выполнение из произвольных путей на кластерах.
Обратите внимание на следующее:
-
Безопасно пересылать файлы только для выполнения из текущей рабочей директории задачи на кластере.
OP = stream IP through 'script'; or DEFINE CMD 'script' ship('/a/b/script'); OP = stream IP through CMD; -
Пересылка файлов по относительным или абсолютным путям не определена и в большинстве случаев завершится ошибкой, так как у вас может не быть разрешений на чтение/запись/выполнение из произвольных путей на фактических кластерах.
О кэшировании
Параметр пересылка работает с двоичными файлами, JAR-файлами и небольшими наборами данных. Однако загрузка больших наборов данных во время выполнения для каждого выполнения может существенно повлиять на производительность. Вместо этого используйте параметр кеш для доступа к большим файлам, которые уже перенесены и доступны на узлах вычислений. С помощью параметра кеш можно указывать только файлы, а не каталоги.
О автоматической пересылке
Если параметры пересылка и кеш не указаны, Pig попытается выполнить автоматическую пересылку следующим образом:
-
Если первым словом в команде потоковой обработки является perl или python, Pig предполагает, что двоичный файл — это первая не заключенная в кавычки строка, которая не начинается с тире.
-
В противном случае Pig попытается переслать первую строку из командной строки, пока она не поступает из /bin, /usr/bin, /usr/local/bin. Pig определит это, просканировав путь, если указан абсолютный путь, или выполнив which. Пути можно сделать настраиваемыми, используя параметр set stream.skippath (вы можете использовать несколько команд set для указания более одного пути для пропуска).
Если для данной команды потоковой обработки вы не предоставите ОПРЕДЕЛЕНИЕ, то автоматическая пересылка будет отключена.
Обратите внимание на следующее:
-
Если Pig определит, что ему необходимо выполнить автоматическую пересылку абсолютного пути, он вообще не будет его пересылать, поскольку нет способа переслать файлы в необходимое место (отсутствуют разрешения и т. д.).
OP = stream IP through `/a/b/c/script`; or OP = stream IP through `perl /a/b/c/script.pl`;
-
Pig не будет автоматически пересылать файлы в следующих системных каталогах (это определяется командой «which <файл>»).
/bin /usr/bin /usr/local/bin /sbin /usr/sbin /usr/local/sbin
-
Для автоматической пересылки файл должен присутствовать в переменной PATH. Таким образом, если файл находится в текущей рабочей директории, то текущая рабочая директория должна быть в переменной PATH.
Примеры: Вход/Выход
В этом примере PigStreaming является функцией сериализации/десериализации по умолчанию. Кортежи из отношения A преобразуются в строки, разделенные табуляцией, которые передаются в скрипт.
X = STREAM A THROUGH `stream.pl`;
В этом примере PigStreaming используется в качестве функции сериализации/десериализации, но в качестве разделителя используется запятая.
DEFINE Y 'stream.pl' INPUT(stdin USING PigStreaming(',')) OUTPUT (stdout USING PigStreaming(','));
X = STREAM A THROUGH Y;
В этом примере используются пользовательские функции сериализации/десериализации со скриптом.
DEFINE Y 'stream.pl' INPUT(stdin USING MySerializer) OUTPUT (stdout USING MyDeserializer); X = STREAM A THROUGH Y;
Примеры: Пересылка/Кеш
В этом примере пересылка используется для отправки скрипта на узлы вычислений кластера.
DEFINE Y 'stream.pl' SHIP('/work/stream.pl');
X = STREAM A THROUGH Y;
В этом примере кеш используется для указания файла, расположенного на узлах вычислений кластера.
DEFINE Y 'stream.pl data.gz' SHIP('/work/stream.pl') CACHE('/input/data.gz#data.gz');
X = STREAM A THROUGH Y;
Пример: ОПРЕДЕЛЕНИЕ с ПОТОКОМ
В этом примере команда определена для использования с оператором ПОТОК.
A = LOAD 'data'; DEFINE mycmd 'stream_cmd –input file.dat'; B = STREAM A through mycmd;
Примеры: Ведение журнала
В этом примере потоковый stderr сохраняется в каталоге _logs/<dir> каталога вывода задачи. Поскольку задача может иметь несколько связанных с ней потоковых приложений, вам необходимо убедиться, что используются разные имена каталогов, чтобы избежать конфликтов. Pig сохраняет до 100 задач на задачу потоковой обработки.
DEFINE Y 'stream.pl' stderr('<dir>' limit 100);
X = STREAM A THROUGH Y;
Примеры: Определение функции
В этом примере функция определена для использования с оператором FOREACH …ГЕНЕРИРОВАТЬ.
REGISTER /src/myfunc.jar
DEFINE myFunc myfunc.MyEvalfunc('foo');
A = LOAD 'students';
B = FOREACH A GENERATE myFunc($0);
РЕГИСТРИРОВАТЬ
Регистрирует JAR-файл, чтобы можно было использовать UDF из файла.
Синтаксис
| РЕГИСТРИРОВАТЬ путь; |
Термины
| путь | Путь к JAR-файлу (требуется полный URI расположения). Имя не должно заключаться в кавычки. |
Использование
Скрипты Pig
Используйте оператор REGISTER внутри скрипта Pig для указания JAR-файла или модуля Python/JavaScript. Pig поддерживает JAR-файлы и модули, хранящиеся в локальных файловых системах, а также в удалённых распределённых файловых системах, таких как HDFS и Amazon S3 (см. Скрипты Pig).
Кроме того, JAR-файлы, хранящиеся в локальных файловых системах, можно указать как шаблон подстановки с использованием «*». Pig будет искать соответствующие JAR-файлы в локальной файловой системе, либо по относительному пути (относительно вашей рабочей директории), либо по абсолютному пути. Pig будет собирать все JAR-файлы, соответствующие шаблону.
Командная строка
Вы можете зарегистрировать дополнительные файлы (для использования со скриптом Pig) через переменную среды PIG_OPTS, используя параметр -Dpig.additional.jars.uris. Дополнительную информацию см. в Пользовательских функциях.
Примеры
В этом примере REGISTER указывает, что JavaScript-модуль myfunc.js находится в каталоге /src.
/src $ java -jar pig.jar – REGISTER /src/myfunc.js; A = LOAD 'students'; B = FOREACH A GENERATE myfunc.MyEvalFunc($0);
В этом примере дополнительные JAR-файлы регистрируются через переменную среды PIG_OPTS.
export PIG_OPTS="-Dpig.additional.jars.uris=my.jar,your.jar"
В этом примере регистрируется JAR-файл, хранящийся в HDFS, и локальный JAR-файл.
export PIG_OPTS="-Dpig.additional.jars.uris=hdfs://nn.mydomain.com:9020/myjars/my.jar,file:///home/root/pig/your.jar"
Обратите внимание, что устаревшее свойство pig.additional.jars, использующее двоеточие в качестве разделителя, по-прежнему поддерживается. Однако мы рекомендуем использовать pig.additional.jars.uris, так как двоеточие также используется в схеме URL, и, следовательно, мы не можем использовать полную схему в списке. Мы планируем убрать pig.additional.jar из будущих релизов.
Этот пример демонстрирует, как указать шаблон glob, используя либо относительный, либо абсолютный путь.
register /homes/user/pig/myfunc*.jar register count*.jar register jars/*.jar
© 2007–2016 Apache Software Foundation
Licensed under the Apache Software License version 2.0.
https://pig.apache.org/docs/r0.15.0/basic.html