Я использовал следующие два подхода для того, чтобы загрузить данные в базу данных кластера (HBase):
- CSV -> HDFS Я часто есть данные в формате CSV. Оказалось довольно сложным для автоматизации процесса превращения CSV-файла в таблицу базы данных Hive/Impala. Вот необходимые шаги:
a. прочитайте файл csv и выполните необходимые преобразования. Важно проанализировать имена столбцов данных в файле csv, однако необходимо создать копию файла, который не содержит строку заголовка.
b. Затем я создаю папку на имя узла машины кластера (до сих пор не HDFS)
mkdir -p input
гр. и скопировать мой файл CSV (без строки заголовка) в папку, созданную выше, используя библиотеку Java JSch, который поддерживает протокол SFTP:
public static void copyFileToLinux(String dest, String user, String password, String file) throws JSchException, SftpException, FileNotFoundException {
String destination = "/home/"+user+"/"+dest;
jsch = new JSch();
session = jsch.getSession(user,"host",22);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelSftp channel = null;
channel = (ChannelSftp)session.openChannel("sftp");
channel.connect();
File localFile = new File(file);
channel.cd(destination);
channel.put(new FileInputStream(localFile),localFile.getName());
channel.disconnect();
session.disconnect();
}
Вот зависимость для JSch:
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.53</version>
</dependency>
д. когда файл CSV находится на главной машине Linux это можно легко положить в HDFS следующие команды (я сначала удалить потенциально настоящий файл с таким же именем):
hdfs dfs -rm input/file.csv
hdfs dfs -mkdir -p input
hdfs dfs -put input/file.csv input
е. как только файл находится в HDFS, я изменяю права на 777 (пояснение по пункту bullet g)
hdfs dfs -chmod -R 777 /user/vKey/input
f. Теперь все готово к созданию таблицы, которые можно сделать с помощью следующего сценария Баша:
#!/bin/bash
path=$1
table_name=$2
impala-shell -i host -q "DROP TABLE IF EXISTS $2;"
impala-shell -i host -q "CREATE EXTERNAL TABLE $2 (c1 INTEGER,c2 STRING,c3 INTEGER,c4 INTEGER,c5 STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' STORED AS TEXTFILE LOCATION '/user/vKey/input';"
Я создаю этот CreateTable.sh скрипт программно. Имена столбцов для сценария взяты из шага а). Помните, что загруженные данные не имеют имен столбцов.Для каждого столбца важно знать его тип, поэтому я написал код, который анализирует первые n строк файла csv и угадывает, есть ли в столбцах целочисленные, двойные, даты или строковые значения. Скрипт затем копируется в папку сценария, который создается заранее:
mkdir -p scripts
Скрипт выполнен:
sh scripts/CreateTable.sh input/file.csv schema.table
Для выполнения этого сценария пользователь импала должен иметь необходимые права для csv файл. Вот почему шаг е) важен.
- JDBC -> HDFS Гораздо проще копировать данные в таблицу HDFS при чтении данных непосредственно из базы данных. Поэтому можно использовать инструмент sqoop.
На первом этапе создается паркет файл:
sqoop import --connect jdbc:oracle:thin:@//host:1521/service --username user -P --table schema.table --target-dir hdfs:////data/schema/table -m 1 --as-parquetfile
Затем таблицу можно создать из файла паркета:
#!/bin/bash
parquet_path=$1
table_name=$2
schema=$3
hadoop fs -setfacl -R -m group:hive:rwx $parquet_path
par_file_list=`hadoop fs -ls $parquet_path | tail -n 1`
par_file=${par_file_list##* }
impala-shell -i host -q "DROP TABLE IF EXISTS $schema.$table_name;"
prefix="hdfs://"
parquet_without_hdfs=${parquet_path#$prefix}
impala-shell -i host -q "CREATE EXTERNAL TABLE $schema.$table_name LIKE PARQUET '$par_file'
STORED AS PARQUET
LOCATION '$parquet_path';"
Недостаток, который вы обычно не может манипулировать/преобразуйте данные между ними, как вы можете делать с csv-файлами, но вместо этого вы берете данные как есть из базы данных. Можно добавить предложение where в оператор sqoop, но нельзя использовать конкретный оператор select.