Основы 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), вы по-прежнему можете ссылаться на поля с использованием позиционной нотации. Однако для отладки и удобства восприятия лучше использовать имена полей.
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 | 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;
-
Если схема определена как часть операторного выражения load, функция load попытается применить схему. Если данные не соответствуют схеме, загрузчик сгенерирует значение 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 …
Все типы данных имеют соответствующие схемы.
Кортеж
Кортеж — это упорядоченный набор полей.
Синтаксис
| ( поле [, поле …] ) |
Термины
| ( ) | Кортеж заключен в круглые скобки ( ). |
| поле | Фрагмент данных. Поле может быть любого типа данных (включая кортеж и мешок). |
Использование
Вы можете рассматривать кортеж как строку с одним или несколькими полями, где каждое поле может быть любого типа данных, и любое поле может или не может содержать данные. Если поле не содержит данных, происходит следующее:
-
В операторном выражении load загрузчик вставит null в кортеж. Фактическое значение, которое подставляется вместо null, зависит от загрузчика; например, PigStorage подставляет пустое поле вместо null.
-
В операторном выражении, отличном от load, если запрашиваемое поле отсутствует в кортеже, 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)})
Карта
Карта представляет собой набор пар ключ/значение.
Синтаксис (<> обозначает необязательное)
| [ ключ#значение <, ключ#значение …> ] |
Термины
| [ ] | Карты заключены в прямые скобки [ ]. |
| # | Пары ключ-значение разделяются знаком решетки #. |
| ключ | Должен быть типом данных chararray. Должен быть уникальным значением. |
| значение | Любой тип данных (по умолчанию bytearray). |
Использование
Значения ключей в отношении должны быть уникальными.
См. также схемы карт.
Пример
В этом примере карта содержит две пары ключ-значение.
[name#John,phone#5551212]
Значения NULL и Pig Latin
В Pig Latin значения NULL реализуются с использованием определения SQL NULL как неизвестного или несуществующего. Значения NULL могут возникать естественным образом в данных или быть результатом операции.
NULL, операторы и функции
Операторы и функции Pig Latin взаимодействуют со значениями NULL, как показано в этой таблице.
| Оператор | Взаимодействие |
| Операторы сравнения: ==, != >, < >=, <= | Если хотя бы одно подвыражение равно NULL, результат равен NULL. |
| Оператор сравнения: matches | Если строка, с которой производится сопоставление, или строка, определяющая сопоставление, равна NULL, результат равен NULL. |
| Арифметические операторы: + , -, *, / % модуль ? : 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 с одним отношением записи с нулевым ключом группируются вместе.
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) с несколькими отношениями записи с нулевым ключом из разных отношений считаются различными и группируются отдельно. В примере ниже обратите внимание, что в выходных данных есть два кортежа, соответствующих нулевому ключу: один, содержащий кортежи из отношения 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'; и вы можете указать символ в Unicode, начав его с '\u', например, '\u0001' представляет Ctrl-A в шестнадцатеричном формате (см. Wikipedia ASCII, Unicode и UTF-8). Теоретически вы должны иметь возможность указать константы, отличные от UTF-8, в не-UTF-8 системах, но, насколько нам известно, это не было проверено.
-
Для указания длинной константы необходимо добавить 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, boolean, ссылка, знак и приведение типа)
-
Любую встроенную функцию Pig.
-
Любую пользовательскую функцию (UDF), написанную на Java.
В Pig Latin,
-
Арифметическое выражение может выглядеть так:
X = GROUP A BY f2*f3;
-
Строковое выражение может выглядеть так, где a и b — оба chararray:
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 не считает boolean базовым типом, результатом общего выражения не может быть boolean. Выражения полей являются простейшими общими выражениями.
Схемы
Схемы позволяют назначать имена полям и объявлять типы полей. Схемы необязательны, но мы рекомендуем использовать их всякий раз, когда это возможно; объявления типов приводят к лучшему обнаружению ошибок во время анализа и более эффективному выполнению кода.
Схемы для простых типов и сложных типов могут быть использованы везде, где уместны определения схем.
Схемы определяются операторами 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). |
| bincond | ? : | (условие ? значение_если_истина : значение_если_ложь) Bincond должен быть заключен в скобки. Схемы двух условных результатов bincond должны совпадать. Используйте только выражения (операторы сравнения запрещены). |
| case | CASE WHEN THEN ELSE END | CASE выражение [ WHEN значение THEN значение ]+ [ ELSE значение ]? END CASE [ WHEN условие THEN значение ]+ [ ELSE значение ]? END Оператор Case эквивалентен вложенным операторам bincond. Схемы всех результатов ветвей when/else должны совпадать. Используйте только выражения (операторы сравнения запрещены). |
Примеры
Предположим, у нас есть таблица А.
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)
В этом примере оператор bincond используется с полями 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, возвращается 'четное'; если равно 1, возвращается 'нечетное'.
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 | |||
| ... (rest of the table) ... |
Таблица типов: операторы умножения (*) и деления (/)
* bytearray приводится к этому типу данных
| bag | tuple | map | int | long | float | double | chararray | bytearray | |
| bag | ошибка | ошибка | ошибка | ещё нет | ещё нет | ещё нет | ещё нет | ошибка | ошибка |
| tuple | ошибка | ошибка | ещё нет | ещё нет | ещё нет | ещё нет | ошибка | ошибка | |
| map | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ||
| int | int | long | float | double | ошибка | преобразование в int | |||
| long | long | float | double | ошибка | преобразование в long | ||||
| float | float | double | ошибка | преобразование в float | |||||
| double | double | ошибка | преобразование в double | ||||||
| chararray | ошибка | ошибка | |||||||
| bytearray | преобразование в double |
Таблица типов: оператор modulo (%)
| int | long | bytearray | |
| int | int | long | преобразование в int |
| long | long | преобразование в long | |
| bytearray | ошибка |
Булевы операторы
Описание
| Оператор | Символ | Примечания |
| И | and | |
| ИЛИ | or | |
| В | in | Оператор IN эквивалентен вложенным операторам ИЛИ. |
| НЕ | not |
Результат булевого выражения (выражения, содержащего булевы и сравнительные операторы) всегда является типом boolean (истина или ложь).
Пример
X = FILTER A BY (f1==8) OR (NOT (f2+f3 > f1)) OR (f1 IN (9, 10, 11));
Операторы приведения типов
Описание
Pig Latin поддерживает приведения типов, как показано в этой таблице.
| от / до | мешок | кортеж | словарь | целое | длинное целое | вещественное | двойное | символьный массив | байтовый массив | булево |
| мешок | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| кортеж | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| словарь | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| целое | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| длинное целое | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| вещественное | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| двойное | ошибка | ошибка | ошибка | да | да | да | да | ошибка | ошибка | |
| символьный массив | ошибка | ошибка | ошибка | да | да | да | да | ошибка | да | |
| байтовый массив | да | да | да | да | да | да | да | да | да | |
| булево | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | да | ошибка |
Синтаксис
| {(тип_данных) | (кортеж(тип_данных)) | (мешок{кортеж(тип_данных)}) | (словарь[]) } поле |
Термины
| (тип_данных) | Тип данных, к которому вы хотите привести, заключённый в скобки. Вы можете привести к любому типу данных, кроме байтового массива (см. таблицу выше). |
| поле | Поле, тип которого вы хотите изменить. Поле может быть представлено позиционным обозначением или по имени (псевдониму). Например, если f1 является первым полем и типом целое, вы можете привести к типу длинное целое, используя (длинное целое)$0 или (длинное целое)f1. |
Использование
Операторы приведения позволяют привести или преобразовать данные из одного типа в другой, если преобразование поддерживается (см. таблицу выше). Например, предположим, что у вас есть поле целого типа, myint, которое вы хотите преобразовать в строку. Вы можете привести это поле от целого к символьному массиву, используя (символьный массив)myint.
Обратите внимание на следующее:
-
Поле можно явно привести. После приведения поле сохраняет этот тип (оно не преобразуется обратно автоматически). В этом примере $0 явно приводится к целому.
B = FOREACH A GENERATE (int)$0 + 1;
-
По возможности Pig выполняет неявные преобразования. В этом примере $0 приводится к целому (независимо от базовых данных), а $1 — к двойному.
B = FOREACH A GENERATE $0 + 1, $1 + 1.0
-
Когда два байтовых массива используются в арифметических выражениях или выражение байтового массива используется с встроенными агрегатными функциями (такими как SUM), они неявно приводятся к двойному. Если базовые данные — это целое или длинное целое, вы получите лучшую производительность, объявив тип или явно приведя данные.
-
Приведение типов может привести к потере данных. Например, приведение от длинного целого к целому может привести к отбрасыванию битов.
Примеры
В этом примере целое приводится к типу символьный массив (см. отношение 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}
В этом примере байтовый массив (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))
В этом примере байтовый массив (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)})
В этом примере байтовый массив (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. Также, если схема не может быть определена, используется байтовый массив.
Основной случай использования преобразования отношений в скаляры — возможность использования значений глобальных агрегатов в последующих вычислениях.
В этом примере вычисляется процент кликов, принадлежащих конкретному пользователю. Для оператора 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 | кортеж | карта | int | long | float | double | chararray | bytearray | boolean | datetime | biginteger | bigdecimal | |
| bag | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка |
| кортеж | boolean (см. Примечание 1) | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | ошибка | |
| карта | 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 | tuple | map | int | long | float | double | chararray | bytearray | boolean | datetime | biginteger | bigdecimal | |
| bag | error | error | error | error | error | error | error | error | error | error | error | error | error |
| tuple | error | error | error | error | error | error | error | error | error | error | error | error | |
| map | error | error | error | error | error | error | error | error | error | error | error | ||
| int | boolean | boolean | boolean | boolean | error | boolean (bytearray cast as int) | error | error | error | error | |||
| long | boolean | boolean | boolean | error | boolean (bytearray cast as long) | error | error | error | error | ||||
| float | boolean | boolean | error | boolean (bytearray cast as float) | error | error | error | error | |||||
| double | boolean | error | boolean (bytearray cast as double) | error | error | error | error | ||||||
| chararray | boolean | boolean (bytearray cast as chararray) | error | error | error | error | |||||||
| bytearray | boolean | error | error | error | error | ||||||||
| boolean | boolean | error | error | error | |||||||||
| datetime | boolean | error | error | ||||||||||
| biginteger | boolean | error | |||||||||||
| bigdecimal | boolean |
Таблица типов: оператор matches
*Преобразование в chararray (вторым аргументом должен быть chararray)
| chararray | bytearray* | |
| chararray | boolean | boolean |
| bytearray | boolean | boolean |
Операторы создания типов
Описание
| Оператор | Символ | Примечания |
| Конструктор кортежа | ( ) | Используется для создания кортежа из указанных элементов. Эквивалентно TOTUPLE. |
| Конструктор множества | { } | Используется для создания множества из указанных элементов. Эквивалентно TOBAG. |
| Конструктор карты | [ ] | Используется для создания карты из указанных элементов. Эквивалентно TOMAP. |
Обратите внимание на следующее:
- Эти операторы могут использоваться везде, где допустимо выражение соответствующего типа, включая FOREACH GENERATE, FILTER и т.д.
- Один элемент, заключенный в скобки ( ), например (5), не считается кортежем, а скорее арифметическим оператором.
- Для множеств каждый элемент помещается в множество; если элемент не является кортежем, Pig создаст для него кортеж:
- При этом {$1, $2} Pig создает это {($1), ($2)} множество с двумя кортежами
... ни $1, ни $2 не являются кортежами, поэтому Pig создает кортеж вокруг каждого элемента
- При этом {($1), $2} Pig создает это {($1), ($2)} множество с двумя кортежами
... поскольку ($1) рассматривается как $1 (нельзя создать кортеж с одним элементом, используя этот синтаксис), {($1), $2} становится {$1, $2}, и Pig создает кортеж вокруг каждого элемента
- При этом {($1, $2)} Pig создает это {($1, $2)} множество с одним кортежем
... Pig создает кортеж ($1, $2), а затем помещает этот кортеж в множество
- При этом {$1, $2} Pig создает это {($1), ($2)} множество с двумя кортежами
Примеры
Создание кортежа
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)
Создание множества
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#'ключ' | Распаковка карты должна выполняться по ключу (field_name#ключ или $0#ключ). Если оператор решетки применяется к 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 синтаксически похож на 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
Описание
| Оператор | Символ | Примечания |
| is null | is null | |
| is not null | is not 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 expression [, message]; |
Термины
| alias | Имя отношения. |
| BY | Обязательное ключевое слово. |
| expression | Булево выражение. |
| message | Сообщение об ошибке при сбое утверждения. |
Использование
Используйте 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. Разделитель управляет разбиением ключей промежуточных выходных данных 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
Выполняет операции куба/сворачивания.
Операция куба
Операция куба вычисляет агрегаты для всех возможных комбинаций указанных группирующих измерений. Количество комбинаций группировки, созданных кубом для n измерений, будет равно 2^n.
Операция сворачивания
Операции сворачивания вычисляют несколько уровней агрегатов на основе иерархического упорядочения указанных группирующих измерений. Сворачивание полезно, когда существует иерархическое упорядочение по измерениям. Количество комбинаций группировки, созданных сворачиванием для n измерений, будет равно n+1.
Синтаксис
| alias = CUBE alias BY { CUBE expression | ROLLUP expression }, [ CUBE expression | ROLLUP expression ] [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| CUBE | Ключевое слово |
| BY | Ключевое слово |
| expression | Проекции (измерения) отношения. Поддерживает выражения поля, звезды и диапазона проекций. |
| 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) приведенный выше запрос с операцией куба выведет
(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)}} Обратите внимание на второй столбец, поле «куб», которое представляет собой набор всех кортежей, принадлежащих к «группе». Обратите также внимание, что атрибут меры «sales» вместе с другими неиспользуемыми измерениями в операторе загрузки передаются вниз, чтобы его можно было использовать позже при вычислении агрегатов по мере, как в этом случае 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) приведенный выше запрос с операцией сворачивания выведет
(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 используются вместе, выходные группы будут декартовым произведением всех групп, сгенерированных операцией куба и сворачивания. Если в операциях куба m измерений, а в операции сворачивания 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) приведенный выше запрос с операцией куба и сворачивания выведет
(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)}} Обработка значений NULL в измерениях
Поскольку значения NULL используются для представления итогов в операции куба и сворачивания, для того чтобы различать законные значения NULL, которые уже существуют как значения измерений, оператор CUBE преобразует любые значения NULL в измерениях в значение «unknown» перед выполнением операции куба или сворачивания. Например, для CUBE(product,location) с образцом кортежа (car,) выход будет равен
(car,unknown) (car,) (,unknown) (,)
DEFINE
См.:
DISTINCT
Удаляет повторяющиеся кортежи в отношении.
Синтаксис
| alias = DISTINCT alias [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя отношения. |
| PARTITION BY partitioner | Используйте эту функцию, чтобы указать Hadoop 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 expression; |
Термины
| alias | Имя отношения. |
| BY | Обязательное ключевое слово. |
| expression | Булево выражение. |
Использование
Используйте оператор 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 }; |
Термины
| alias | Имя отношения (внешний пакет). |
| block | Блок FOREACH…GENERATE, используемый с отношением (внешний пакет). Используйте этот синтаксис: alias = FOREACH alias GENERATE expression [AS schema] [expression [AS schema]….]; См. Схемы |
| nested_block | Вложенный блок FOREACH…GENERATE, используемый с внутренним пакетом. Используйте этот синтаксис: alias = FOREACH nested_alias { alias = {nested_op | nested_exp}; [{alias = {nested_op | nested_exp}; …] GENERATE expression [AS schema] [expression [AS schema]….] }; Где: Вложенный блок заключён в открывающие и закрывающие скобки { … }. Ключевое слово GENERATE должно быть последним оператором внутри вложенного блока. См. Схемы Макросы НЕ разрешены внутри вложенного блока. |
| expression | Выражение. |
| nested_alias | Имя внутреннего пакета. |
| nested_op | Разрешённые операции: CROSS, DISTINCT, FILTER, FOREACH, LIMIT и ORDER BY. Примечание: Вложенные операторы FOREACH могут быть только до двух уровней. Операторы FOREACH, вложенные на три или более уровня, приведут к синтаксической ошибке. Вы также можете выполнять проекции внутри вложенного блока. Примеры см. в Примере: Вложенный блок. |
| nested_exp | Любое произвольное поддерживаемое выражение. |
| AS | Ключевое слово |
| schema | Схема, использующая ключевое слово 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)
Другой пример развёртывания.
X = FOREACH C GENERATE GROUP, FLATTEN(A.a3); DUMP X; (1,3) (4,1) (4,3) (8,4) (8,3)
Другой пример развёртывания. Обратите внимание, что для группы '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)
Другой пример развёртывания. Здесь отношения 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
Группирует данные в одном или нескольких отношениях.
Примечание: Операторы GROUP и COGROUP идентичны. Оба оператора работают с одним или несколькими отношениями. Для читабельности GROUP используется в операциях с одним отношением, а COGROUP используется в операциях с двумя или более отношениями. Одновременно можно использовать COGROUP до 127 отношений.
Синтаксис
| alias = GROUP alias { ALL | BY expression} [, alias ALL | BY expression …] [USING 'collected' | 'merge'] [PARTITION BY partitioner] [PARALLEL n]; |
Термины
| alias | Имя отношения. Одновременно можно использовать COGROUP до 127 отношений. |
| ALL | Ключевое слово. Используйте ALL, если вы хотите, чтобы все кортежи попали в одну группу, например, при выполнении агрегаций по всем отношениям. B = GROUP A ALL; |
| BY | Ключевое слово. Используйте этот оператор для группировки отношения по полю, кортежу или выражению. B = GROUP A BY f1; |
| expression | Кортеж выражение. Это ключ группы или ключевое поле. Если результат выражения кортежа — одно поле, ключ будет значением первого поля, а не кортежа с одним полем. Для группировки по нескольким ключам заключите ключи в скобки: 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) и имеет тот же тип, что и ключ группы.
-
Второе поле принимает имя исходного отношения и имеет тип пакет.
-
Имена обоих полей генерируются системой, как показано в примере ниже.
Обратите внимание на следующее в отношении операторов 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 имеет два поля. Первое поле называется «group» и имеет тип 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 по именам «group» и «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 обрабатывают нулевые значения по-разному (см. Nulls и оператор 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 опущен.
Обратите внимание на следующее:
-
Внешние соединения будут работать только при условии, что отношения, которые должны создавать 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)
В этом примере вывод ограничивается 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 globing для указания файлов на уровне файла или каталога (см. Hadoop globStatus для получения подробной информации о синтаксисе globing). Примечание: 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 {`команда` | псевдоним_команды } [AS схема] ; |
Термины
| псевдоним | Имя отношения. |
| THROUGH | Ключевое слово. |
| `команда` | Команда, включая аргументы, заключённые в обратные кавычки (где команда — это всё, что может быть выполнено). |
| псевдоним_команды | Имя команды, созданной с помощью оператора DEFINE (см. DEFINE (UDFs, потоковая передача) для дополнительных примеров потоковой передачи). |
| AS | Ключевое слово. |
| схема | Схема с использованием ключевого слова AS, заключённая в скобки (см. Схемы). |
Использование
Используйте оператор STREAM для отправки данных через внешнюю скрипт или программу. Несколько операторов stream могут появляться в одном скрипте Pig. Операторы stream могут быть расположены рядом друг с другом или между ними могут быть другие операции.
При использовании с командой оператор stream может выглядеть так:
A = LOAD 'data'; B = STREAM A THROUGH `stream.pl -n 5`;
При использовании с псевдонимом команды, оператор 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 для определения объединения по именованным полям (вместо позиционного обозначения). Все входные данные для объединения должны иметь не неопределенную (не нулевую) схему. |
Использование
Используйте оператор 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
ОПРЕДЕЛИТЬ (UDFs, потоковая обработка)
Присваивает псевдоним UDF или команде потоковой обработки.
Синтаксис: UDF и потоковая обработка
| ОПРЕДЕЛИТЬ псевдоним {функция | [`команда` [вход] [выход] [пересылка] [кэш] [ошибка] ] }; |
Термины
| псевдоним | Имя функции UDF или имя команды потоковой обработки (cmd_alias для оператора STREAM). |
| функция | Для использования с функциями. Имя функции UDF. |
| `команда` | Для использования с потоковой обработкой. Команда, включая аргументы, заключенная в обратные кавычки (любая команда, которую можно выполнить). Описания пунктов (вход, выход, пересылка, кэш, ошибка) приведены ниже. Обратите внимание на следующее:
|
| вход | Для использования с потоковой обработкой. ВХОД ( {stdin | 'путь'} [Используя сериализатор] [, {stdin | 'путь'} [Используя сериализатор] …] ) Где:
|
| выход | Для использования с потоковой обработкой. ВЫХОД ( {stdout | stderr | 'путь'} [Используя десериализатор] [, {stdout | stderr | 'путь'} [Используя десериализатор] …] ) Где:
|
| пересылка | Для использования с потоковой обработкой. ПЕРЕСЫЛКА('путь' [, 'путь' …]) Где:
|
| кэш | Для использования с потоковой обработкой. КЭШ('dfs_путь#dfs_файл' [, 'dfs_путь#dfs_файл' …]) Где:
|
| ошибка | Для использования с потоковой обработкой. 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.
С помощью опции пересылки можно указывать только файлы, а не каталоги. Один из способов обойти это ограничение — создать архив всех зависимостей в файле tar, который точно отражает необходимую структуру на узлах обработки, а затем создать оболочку для своего скрипта, которая будет распаковывать зависимости перед выполнением.
Обратите внимание, что опция пересылки имеет два компонента: указание источника в пункте пересылки отражает вашу машину; указание команды отражает фактический кластер. Единственная гарантия — файлы, переданные для пересылки, будут доступны в текущей рабочей директории запущенной задачи, а текущая рабочая директория также будет указана в переменной окружения 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 <file>' ).
/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;
Пример: ОПРЕДЕЛИТЬ с STREAM
В этом примере для использования с оператором STREAM определяется команда.
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 …GENERATE.
REGISTER /src/myfunc.jar
DEFINE myFunc myfunc.MyEvalfunc('foo');
A = LOAD 'students';
B = FOREACH A GENERATE myFunc($0);
ЗАРЕГИСТРИРОВАТЬ
Регистрирует JAR-файл, чтобы можно было использовать UDF в нём.
Синтаксис
| ЗАРЕГИСТРИРОВАТЬ путь; |
Термины
| путь | Путь к JAR-файлу (требуется полный URI расположения). Не заключайте имя в кавычки. |
Использование
Скрипты Pig
Используйте оператор ЗАРЕГИСТРИРОВАТЬ внутри скрипта 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.14.0/basic.html