Carga de datos en distintos formatos#
Última modificación: Mayo 17, 2022 | YouTube
Hive permite la lectura de archivos en distintos formatos. Al finalizar este tutorial, el lector estará en capacidad de leer archivos en formatos de texto, CSV y JSON.
Cell magic %%hive
#
[1]:
from IPython.core.magic import Magics, cell_magic, line_magic, magics_class
from pexpect import spawn
TIMEOUT = 60
PROG = "hive"
PROMPT = ["\r\n > ", "\r\nhive> "]
QUIT = "quit;"
@magics_class
class Magic(Magics):
def __init__(self, shell):
super().__init__(shell)
self.app = spawn(PROG, timeout=60)
self.app.expect(PROMPT)
@cell_magic
def hive(self, line, cell):
cell_lines = [cell_line.strip() for cell_line in cell.split("\n")]
cell_lines = [cell_line for cell_line in cell_lines if cell_line != ""]
for cell_line in cell_lines:
self.app.sendline(cell_line)
self.app.expect(PROMPT, timeout=TIMEOUT)
output = self.app.before.decode()
output = output.replace("\r\n", "\n")
output = output.split("\n")
output = [output_line.strip() for output_line in output]
for output_line in output:
if output_line not in cell_lines:
print(output_line)
return None
@line_magic
def quit(self, line):
self.app.sendline(QUIT)
def load_ipython_extension(ip):
ip.register_magics(Magic(ip))
load_ipython_extension(ip=get_ipython())
Preparación#
[2]:
#
# Crea la carpeta drivers en el HDFS
#
!hdfs dfs -rm -r -f /tmp/drivers
!hdfs dfs -mkdir /tmp/drivers
Deleted /tmp/drivers
[3]:
!wget https://raw.githubusercontent.com/jdvelasq/datalabs/master/datasets/drivers/drivers.csv
--2022-05-17 16:15:55-- https://raw.githubusercontent.com/jdvelasq/datalabs/master/datasets/drivers/drivers.csv
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2043 (2.0K) [text/plain]
Saving to: ‘drivers.csv’
drivers.csv 100%[===================>] 2.00K --.-KB/s in 0.001s
2022-05-17 16:15:56 (2.69 MB/s) - ‘drivers.csv’ saved [2043/2043]
[4]:
!wget https://raw.githubusercontent.com/jdvelasq/datalabs/master/datasets/drivers/drivers.json
--2022-05-17 16:15:56-- https://raw.githubusercontent.com/jdvelasq/datalabs/master/datasets/drivers/drivers.json
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4308 (4.2K) [text/plain]
Saving to: ‘drivers.json’
drivers.json 100%[===================>] 4.21K --.-KB/s in 0.002s
2022-05-17 16:15:56 (1.80 MB/s) - ‘drivers.json’ saved [4308/4308]
Lectura de formato JSON desde un archivo cargado como texto#
En esta estrategía de carga de datos, el archivo original con formato JSON es cargado como texto, donde cada registro de la tabla corresponde a una línea del archivo original.
[5]:
#
# Copia el archivo al HDFS para su importación posterior a Hive
#
!hdfs dfs -copyFromLocal drivers.json /tmp/drivers/
[6]:
!hdfs dfs -ls /tmp/drivers/
Found 1 items
-rw-r--r-- 1 root supergroup 4308 2022-05-17 16:15 /tmp/drivers/drivers.json
En la siguiente celda, se crea la tabla drivers_raw_json
, la cual tiene una única columna llamada textcol
. Luego, el archivo drivers.json
es cargado en dicha tabla. Finalmente, se visualizan los primeros cinco registros para verificar que la lectura fue correcta.
[7]:
%%hive
DROP TABLE IF EXISTS drivers_raw_json;
CREATE TABLE drivers_raw_json (
textcol STRING
)
STORED AS TEXTFILE;
LOAD DATA INPATH
'/tmp/drivers/drivers.json'
OVERWRITE INTO TABLE drivers_raw_json;
SELECT * FROM drivers_raw_json LIMIT 5;
OK
Time taken: 5.677 seconds
OK
Time taken: 0.554 seconds
Loading data to table default.drivers_raw_json
OK
Time taken: 0.622 seconds
OK
{"driverId":10,"name":"George Vetticaden","ssn":621011971,"location":"244-4532 Nulla Rd.","certified":"N","wage-plan":"miles"}
{"driverId":11,"name":"Jamie Engesser","ssn":262112338,"location":"366-4125 Ac Street","certified":"N","wage-plan":"miles"}
{"driverId":12,"name":"Paul Coddin","ssn":198041975,"location":"Ap #622-957 Risus. Street","certified":"Y","wage-plan":"hours"}
{"driverId":13,"name":"Joe Niemiec","ssn":139907145,"location":"2071 Hendrerit. Ave","certified":"Y","wage-plan":"hours"}
{"driverId":14,"name":"Adis Cesir","ssn":820812209,"location":"Ap #810-1228 In St.","certified":"Y","wage-plan":"hours"}
Time taken: 1.021 seconds, Fetched: 5 row(s)
Note que en la salida anterior, cada fila corresponde a un registro.
Lectura usando get_json_object#
Los valores de los campos pueden ser extraídos usando la función get_json_object
, cuyos parámetros son el nombre del campo en la tabla y el nombre del campo en la estructura JSON. En el siguiente fragmento de código, se utiliza una consulta para extraer los campos driverId
, name
y ssn
.
[8]:
%%hive
SELECT
GET_JSON_OBJECT(textcol,'$.driverId'),
GET_JSON_OBJECT(textcol,'$.name'),
GET_JSON_OBJECT(textcol,'$.ssn')
FROM
drivers_raw_json
LIMIT
10;
OK
10 George Vetticaden 621011971
11 Jamie Engesser 262112338
12 Paul Coddin 198041975
13 Joe Niemiec 139907145
14 Adis Cesir 820812209
15 Rohit Bakshi 239005227
16 Tom McCuch 363303105
17 Eric Mizell 123808238
18 Grant Liu 171010151
19 Ajay Singh 160005158
Time taken: 0.315 seconds, Fetched: 10 row(s)
Uso de json_tuple#
Esta función cumple el mismo objetivo de la anterior, pero es mucho más eficiente ya que el registro es procesado únicamente una vez para realizar la extracción de la información requerida. Ya que json_tuple
es una UDF, debe usarse LATERAL VIEW
para realizar la consulta, tal como se ejemplifica a continuación.
[9]:
%%hive
SELECT
t1.driverId,
t1.name,
t1.ssn
FROM
drivers_raw_json t0
LATERAL VIEW
JSON_TUPLE(t0.textcol, 'driverId', 'name', 'ssn') t1
AS driverId, name, ssn
LIMIT 5;
OK
10 George Vetticaden 621011971
11 Jamie Engesser 262112338
12 Paul Coddin 198041975
13 Joe Niemiec 139907145
14 Adis Cesir 820812209
Time taken: 0.078 seconds, Fetched: 5 row(s)
Carga de archivos en formato JSON#
Hive también permite la importación directa de archivos en formato JSON usando el serde JsonSerDe
.
[10]:
#
# Se copia el archivo al sistema HDFS
#
!hdfs dfs -copyFromLocal drivers.* /tmp/drivers/
En la siguiente celda, se crea la tabla drivers_json
donde el formato de cada registro es especificado como JSON
[11]:
%%hive
DROP TABLE IF EXISTS drivers_json;
CREATE TABLE drivers_json (
driverId INT,
name STRING,
ssn BIGINT,
location STRING,
certified STRING,
wageplan STRING)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE
LOCATION '/tmp/drivers-json';
LOAD DATA INPATH '/tmp/drivers/drivers.json' OVERWRITE INTO TABLE drivers_json;
SELECT * FROM drivers_json LIMIT 5;
OK
Time taken: 0.021 seconds
OK
Time taken: 0.065 seconds
json;DATA INPATH '/tmp/drivers/drivers.json' OVERWRITE INTO TABLE drivers_
Loading data to table default.drivers_json
OK
Time taken: 0.23 seconds
OK
10 George Vetticaden 621011971 244-4532 Nulla Rd. N NULL
11 Jamie Engesser 262112338 366-4125 Ac Street N NULL
12 Paul Coddin 198041975 Ap #622-957 Risus. Street Y NULL
13 Joe Niemiec 139907145 2071 Hendrerit. Ave Y NULL
14 Adis Cesir 820812209 Ap #810-1228 In St. Y NULL
Time taken: 0.102 seconds, Fetched: 5 row(s)
Carga de archivos en formato CSV#
En este ejemplo se usa el serde OpenCSVSerde
para leer archivo en formato CSV. Note que se usa la cláusula with serdeproperties
para indicar las características del formato CSV utilizado.
[12]:
%%hive
DROP TABLE IF EXISTS drivers_csv;
CREATE TABLE drivers_csv (driverId INT,
name STRING,
ssn BIGINT,
location STRING,
certified STRING,
wageplan STRING)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar' = ",",
'quoteChar' = '\'',
'escapeChar' = "\\");
LOAD DATA INPATH '/tmp/drivers/drivers.csv' OVERWRITE INTO TABLE drivers_csv;
SELECT * FROM drivers_csv LIMIT 5;
OK
Time taken: 0.024 seconds
OK
Time taken: 0.058 seconds
sv;D DATA INPATH '/tmp/drivers/drivers.csv' OVERWRITE INTO TABLE drivers_c
Loading data to table default.drivers_csv
OK
Time taken: 0.204 seconds
OK
driverId name ssn location certified wage-plan
10 George Vetticaden 621011971 244-4532 Nulla Rd. N miles
11 Jamie Engesser 262112338 366-4125 Ac Street N miles
12 Paul Coddin 198041975 Ap #622-957 Risus. Street Y hours
13 Joe Niemiec 139907145 2071 Hendrerit. Ave Y hours
Time taken: 0.103 seconds, Fetched: 5 row(s)
Carga usando expresiones regulaes y RegexSerDe#
En este caso, se realiza la carga de datos especificando los campos mediante el uso de expresiones regulares.
[13]:
#
# Copia los archivos al HDFS
#
!hdfs dfs -copyFromLocal drivers.csv /tmp/drivers/
[14]:
%%hive
DROP TABLE IF EXISTS drivers_regex;
CREATE TABLE drivers_regex(
driverId INT,
name STRING,
ssn BIGINT,
location STRING,
certified STRING,
wageplan STRING)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'input.regex' = '(\\d+),([^,]*),(\\d+),([^,]*),([^,]*),([^,]*)')
TBLPROPERTIES ("skip.header.line.count"="1");
LOAD DATA INPATH '/tmp/drivers/drivers.csv' OVERWRITE INTO TABLE drivers_regex;
SELECT * FROM drivers_regex LIMIT 5;
OK
Time taken: 0.019 seconds
OK
Time taken: 0.059 seconds
egex;DATA INPATH '/tmp/drivers/drivers.csv' OVERWRITE INTO TABLE drivers_r
Loading data to table default.drivers_regex
OK
Time taken: 0.208 seconds
OK
10 George Vetticaden 621011971 244-4532 Nulla Rd. N miles
11 Jamie Engesser 262112338 366-4125 Ac Street N miles
12 Paul Coddin 198041975 Ap #622-957 Risus. Street Y hours
13 Joe Niemiec 139907145 2071 Hendrerit. Ave Y hours
14 Adis Cesir 820812209 Ap #810-1228 In St. Y hours
Time taken: 0.096 seconds, Fetched: 5 row(s)
La expresión regular usada es la siguiente:
(\\d+),([^,]*),(\\d+),([^,]*),([^,]*),([^,]*)`
donde:
Los paréntesis indica los campos, esto es,
(\\d+)
es el primer campo,([^,]*)
es el segundo y así sucesivamente.Se indica que la coma es el separador entre campos.
(\\d+)
representa una cadena de uno o más dígitos.[...]
representan uno o más posibles caracteres, de tal forma que[^,]
indica cualquier caracter excepto una coma. Finalmente, el * indica cero, una o más ocurrencias. Es así como[^,]*
representa cualquier cadena de caracteres que no contenga una coma.La expresión regular usada indica que los campos 1 y 3 son numéricos, y los restantes son texto.
[15]:
%quit
[16]:
!rm drivers.* *.log