Sqoop Import Split by Column Тип данных
Должен ли тип данных Разделить по столбцам при импорте sqoop всегда быть числовым типом данных (целое число, bignint, числовое значение)? Разве это не может быть строка?
3 ответа
Да, вы можете разделить на любой не числовой тип данных.
Но это не рекомендуется.
ЗАЧЕМ?
Для разделения данных Sqoop запускает
SELECT MIN(col1), MAX(col2) FROM TABLE
затем разделите его по количеству картографов.
Теперь возьмите пример целого числа как --split-by
колонка
Таблица имеет некоторые id
столбец со значением от 1 до 100, и вы используете 4 картографов (-m 4
в вашей команде sqoop)
Sqoop получить значения MIN и MAX, используя:
SELECT MIN(id), MAX(id) FROM TABLE
ВЫХОД:
+1100
Разбить на целое число легко. Вы сделаете 4 части:
- 1-25
- 25-50
- 51-75
- 76-100
Теперь строка как --split-by
колонка
Таблица имеет некоторые name
столбец со значением "dev" для "sam" и вы используете 4 мапперов (-m 4
в вашей команде sqoop)
Sqoop получить значения MIN и MAX, используя:
SELECT MIN(id), MAX(id) FROM TABLE
ВЫХОД:
DEV, сэм
Теперь, как это будет разделено на 4 части. Согласно документам sqoop,
/**
* This method needs to determine the splits between two user-provided
* strings. In the case where the user's strings are 'A' and 'Z', this is
* not hard; we could create two splits from ['A', 'M') and ['M', 'Z'], 26
* splits for strings beginning with each letter, etc.
*
* If a user has provided us with the strings "Ham" and "Haze", however, we
* need to create splits that differ in the third letter.
*
* The algorithm used is as follows:
* Since there are 2**16 unicode characters, we interpret characters as
* digits in base 65536. Given a string 's' containing characters s_0, s_1
* .. s_n, we interpret the string as the number: 0.s_0 s_1 s_2.. s_n in
* base 65536. Having mapped the low and high strings into floating-point
* values, we then use the BigDecimalSplitter to establish the even split
* points, then map the resulting floating point values back into strings.
*/
И вы увидите предупреждение в коде:
LOG.warn("Generating splits for a textual index column.");
LOG.warn("If your database sorts in a case-insensitive order, "
+ "this may result in a partial import or duplicate records.");
LOG.warn("You are strongly encouraged to choose an integral split column.");
В случае примера Integer все преобразователи получат сбалансированную нагрузку (все получат 25 записей из RDBMS).
В случае строки вероятность сортировки данных меньше. Таким образом, трудно дать одинаковые нагрузки всем картографам.
В двух словах, перейдите к целому столбцу как --split-by
колонка.
Да, мы можем это сделать, но это не рекомендуется из-за проблем с производительностью. поскольку мы знаем, что SQOOP запускает граничный запрос « выберите min(столбец pk / split-by), max(столбец pk / split-by) из таблицы, где условие » для расчета размера разделения для картографов. split-size = (макс. - мин.)/количество мапперов
Допустим, есть таблица под названием employee.
id name age
1 baba 20
2 kishor 30
3 jay 40
..........
10001 pk 60
Сенарио 1:
Выполнение разделения по столбцу id
В этом случае SQOOP запустит граничный запрос select min(id),max(id) от сотрудника, чтобы вычислить размер разделения.
min = 1
max = 100001
default no of mapper = 4
split-size = (10001-1)/4 = 25000
so each mapper will process 25000 lines of record.
mapper 1: 1 - 25000
mapper 2: 25001-50000
mapper 3: 50001-75000
mapper 4: 75001-100000
поэтому SQOOP очень легко разделить записи, если у нас есть интегральный столбец.
Сценарий 2:
Выполнение разделения по столбцу имени
В этом случае SQOOP запустит «выбрать мин. (имя), макс. (имя) из сотрудника», чтобы вычислить размер разделения.
min = baba, max= pk
SQOOP не сможет легко вычислить размер разделения, потому что min и max имеют текстовые значения ((min-max)/no of mappers), поэтому он будет запускать класс TextSplitter для выполнения разделения, что создаст дополнительные накладные расходы и может повлиять на производительность.
Примечание. Нам нужно передать дополнительный аргумент -D org.apache.sqoop.splitter.allow_text_splitter= true , чтобы использовать класс TextSplitter.
Нет, он должен быть числовым, потому что в соответствии со спецификациями: "По умолчанию sqoop будет использовать запрос select min(), max() from для определения границ для создания разбиений". Альтернативой является использование --boundary-query, который также требует числовых столбцов. В противном случае задание Sqoop не будет выполнено. Если у вас нет такого столбца в вашей таблице, единственный обходной путь - использовать только 1 маппер: "-m 1".