读写HDFS文本数据
PXF HDFS连接器支持纯分隔和逗号分隔的值表单文本数据。 本节介绍如何使用PXF访问HDFS文本数据,包括如何创建引用了HDFS文件的外部表,查询外部表和向外部表写入数据。
先决条件
在尝试从HDFS读取或向HDFS写入数据之前,请确保已满足PXF Hadoop先决条件。
读取文本数据
当您在读取每行都是单条记录的纯文本分隔或csv数据时,请使用hdfs:text配置文件。以下语法创建了一个Greenplum数据库可读外部表,该表引用了HDFS上的此类文本文件:
CREATE EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path-to-hdfs-file>?PROFILE=hdfs:text[&SERVER=<server_name>]')
FORMAT '[TEXT|CSV]' (delimiter[=|<space>][E]'<delim_value>');
CREATE EXTERNAL TABLE命令中使用的特定关键字和值见下表中描述。
| 关键字 | 值 | 
|---|---|
| <path‑to‑hdfs‑file> | HDFS数据存储中目录或文件的绝对路径 | 
| PROFILE | PROFILE关键字必须指定为hdfs:text | 
| SERVER=<server_name> | PXF用于访问数据的命名服务器配置。可选的; 如果未指定,PXF将使用 default服务器。 | 
| FORMAT | 当<path-to-hdfs-file>引用纯文本分隔数据时,请使用 FORMAT'TEXT'。当<path-to-hdfs-file>引用逗号分隔值数据时,请使用 FORMAT'CSV'。 | 
| delimiter | 数据中的分隔符。对于 FORMAT'CSV',默认的<delim_value> 是逗号,。 当分隔符为转义序列时,在<delim_value> 前面加上E。示例:(delimiter=E'\t'),(delimiter ':')。 | 
示例:读取HDFS中的文本数据
执行以下过程来创建示例文本文件,将文件复制到HDFS,然后使用hdfs:text配置文件和默认的PXF服务器创建两个PXF外部表来查询数据:
- 为PXF示例数据文件创建HDFS目录。例如: - $ hdfs dfs -mkdir -p /data/pxf_examples
- 创建名为 - pxf_hdfs_simple.txt的纯文本分割数据文件:- $ echo 'Prague,Jan,101,4875.33 Rome,Mar,87,1557.39 Bangalore,May,317,8936.99 Beijing,Jul,411,11600.67' > /tmp/pxf_hdfs_simple.txt- 注意使用逗号 - ,来分隔四个数据字段。.
- 将数据文件添加到HDFS: - $ hdfs dfs -put /tmp/pxf_hdfs_simple.txt /data/pxf_examples/
- 显示存储在HDFS中的 - pxf_hdfs_simple.txt文件的内容:- $ hdfs dfs -cat /data/pxf_examples/pxf_hdfs_simple.txt
- 启动 - psql子系统:- $ psql -d postgres
- 使用PXF - hdfs:text配置文件创建一个引用刚刚创建并添加到HDFS的- pxf_hdfs_simple.txt文件的Greenplum数据库外部表:- postgres=# CREATE EXTERNAL TABLE pxf_hdfs_textsimple(location text, month text, num_orders int, total_sales float8) LOCATION ('pxf://data/pxf_examples/pxf_hdfs_simple.txt?PROFILE=hdfs:text') FORMAT 'TEXT' (delimiter=E',');
- 查询外部表: - postgres=# SELECT * FROM pxf_hdfs_textsimple;- location | month | num_orders | total_sales ---------------+-------+------------+------------- Prague | Jan | 101 | 4875.33 Rome | Mar | 87 | 1557.39 Bangalore | May | 317 | 8936.99 Beijing | Jul | 411 | 11600.67 (4 rows)
- 创建第二个引用 - pxf_hdfs_simple.txt的外部表,这一次指定- FORMAT为- CSV:- postgres=# CREATE EXTERNAL TABLE pxf_hdfs_textsimple_csv(location text, month text, num_orders int, total_sales float8) LOCATION ('pxf://data/pxf_examples/pxf_hdfs_simple.txt?PROFILE=hdfs:text') FORMAT 'CSV'; postgres=# SELECT * FROM pxf_hdfs_textsimple_csv;- 当您为逗号分隔值数据指定 - FORMAT 'CSV'时,不需要提供- delimiter分隔符选项,因为默认的分隔符是逗号。
读取含有双引号引起来的换行符的文本数据
使用hdfs:text:multi配置文件读取数据中含有引号引起来的换行符,单行或多行的分隔文本数据。以下语法创建一个引用此类文件的Greenplum外部表:
CREATE EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path-to-hdfs-file>?PROFILE=hdfs:text:multi[&SERVER=<server_name>]')
FORMAT '[TEXT|CSV]' (delimiter[=|<space>][E]'<delim_value>');
CREATE EXTERNAL TABLE命令中使用的特定关键字和值见下表中描述。
| 关键字 | 值 | 
|---|---|
| <path‑to‑hdfs‑file> | HDFS数据存储中目录或文件的绝对路径 | 
| PROFILE | PROFILE关键字必须指定为hdfs:text:multi | 
| SERVER=<server_name> | PXF用于访问数据的命名服务器配置。可选的; 如果未指定,PXF将使用 default服务器。 | 
| FORMAT | 当<path-to-hdfs-file>引用纯文本分隔数据时,请使用 FORMAT'TEXT'。当<path-to-hdfs-file>引用逗号分隔值数据时,请使用 FORMAT'CSV'。 | 
| delimiter | 数据中的分隔符。对于 FORMAT'CSV',默认的<delim_value> 是逗号,。 当分隔符为转义序列时,在<delim_value> 前面加上E。示例:(delimiter=E'\t'),(delimiter ':')。 | 
示例:在HDFS上读取多行文本数据
执行以下步骤来创建示例文本文件,将文件复制到HDFS,然后使用PXFhdfs:text:multi配置文件和默认的PXF服务器创建Greenplum数据库可读的外部表来查询数据:
- 创建第二个分隔的纯文本文件: - $ vi /tmp/pxf_hdfs_multi.txt
- 将以下数据复制/黏贴到 - pxf_hdfs_multi.txt中:- "4627 Star Rd. San Francisco, CA 94107":Sept:2017 "113 Moon St. San Diego, CA 92093":Jan:2018 "51 Belt Ct. Denver, CO 90123":Dec:2016 "93114 Radial Rd. Chicago, IL 60605":Jul:2017 "7301 Brookview Ave. Columbus, OH 43213":Dec:2018- 注意使用冒号 - :分隔三个字段。 另外请注意第一个(地址)字段周围的引号。这个字段包含了一个嵌入的换行符,用于将街道地址与城市和州分开。
- 将文本文件复制到HDFS: - $ hdfs dfs -put /tmp/pxf_hdfs_multi.txt /data/pxf_examples/
- 使用 - hdfs:text:multi配置文件创建一个引用HDFS文件- pxf_hdfs_multi.txt的外部表, 确保将- :(冒号) 标识为字段分隔符:- postgres=# CREATE EXTERNAL TABLE pxf_hdfs_textmulti(address text, month text, year int) LOCATION ('pxf://data/pxf_examples/pxf_hdfs_multi.txt?PROFILE=hdfs:text:multi') FORMAT 'CSV' (delimiter ':');- Notice the alternate syntax for specifying the - delimiter.
- 查询 - pxf_hdfs_textmulti表:- postgres=# SELECT * FROM pxf_hdfs_textmulti;- address | month | year --------------------------+-------+------ 4627 Star Rd. | Sept | 2017 San Francisco, CA 94107 113 Moon St. | Jan | 2018 San Diego, CA 92093 51 Belt Ct. | Dec | 2016 Denver, CO 90123 93114 Radial Rd. | Jul | 2017 Chicago, IL 60605 7301 Brookview Ave. | Dec | 2018 Columbus, OH 43213 (5 rows)
将文本文件写入HDFS
PXF HDFS连接器 “hdfs:text” 配置文件支持将单行纯文本数据写入HDFS。 当您使用PXF HDFS连接器创建可写外部表时,可以指定在HDFS上的目录名称。 当您向可写外部表写入数据时,您写入的数据块将写入到指定目录中的一个或多个文件。
注意: 使用可写配置文件创建的外部表只能用于 INSERT 操作。如果要查询写入的数据,则必须另外创建一个引用HDFS目录的可读外部表。
使用以下语法创建一个引用HDFS目录的Greenplum可写外部表:
CREATE WRITABLE EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path-to-hdfs-dir>
    ?PROFILE=hdfs:text[&SERVER=<server_name>][&<custom-option>=<value>[...]]')
FORMAT '[TEXT|CSV]' (delimiter[=|<space>][E]'<delim_value>');
[DISTRIBUTED BY (<column_name> [, ... ] ) | DISTRIBUTED RANDOMLY];
CREATE EXTERNAL TABLE命令中使用的特定关键字和值见下表中描述。
| 关键字 | 值 | 
|---|---|
| <path‑to‑hdfs‑dir> | HDFS数据存储中目录的绝对路径 | 
| PROFILE | PROFILE关键字必须指定为hdfs:text | 
| SERVER=<server_name> | PXF用于访问数据的命名服务器配置。可选的; 如果未指定,PXF将使用 default服务器。 | 
| <custom‑option> | <custom-option>描述见下方 | 
| FORMAT | 当<path-to-hdfs-file>引用纯文本分隔数据时,请使用 FORMAT'TEXT'。当<path-to-hdfs-file>引用逗号分隔值数据时,请使用 FORMAT'CSV'。 | 
| delimiter | 数据中的分隔符。对于 FORMAT'CSV',默认的<delim_value> 是逗号,。 当分隔符为转义序列时,在<delim_value> 前面加上E。示例:(delimiter=E'\t'),(delimiter ':')。 | 
| DISTRIBUTED BY | 如果您计划将现有Greenplum数据库表中的数据加载到可写外部表,考虑在可写外部表上使用Greenplum表相同的分布策略或<字段名>。 这样做可以避免数据加载操作中segment节点间额外的数据移动。 | 
使用 hdfs:text 配置文件创建的可写外部表可以选择使用记录或块压缩。 PXF hdfs:text 配置文件支持以下压缩编解码器:
- org.apache.hadoop.io.compress.DefaultCodec
- org.apache.hadoop.io.compress.GzipCodec
- org.apache.hadoop.io.compress.BZip2Codec
您可以通过 CREATE EXTERNAL TABLE LOCATION 子句中自定义选择指定压缩编解码器。 hdfs:text 配置文件支持以下自定义写入选项:
| 选项 | 值描述 | 
|---|---|
| COMPRESSION_CODEC | 压缩编解码器Java类名。 如果未提供此选项,Greenplum数据库不会执行压缩编码。支持的压缩编解码器包括: org.apache.hadoop.io.compress.DefaultCodecorg.apache.hadoop.io.compress.BZip2Codecorg.apache.hadoop.io.compress.GzipCodec | 
| COMPRESSION_TYPE | 采用的压缩类型; 支持的值为 RECORD(默认) 或BLOCK | 
| THREAD-SAFE | 确定表查询是否可以在多线程模式下运行的布尔值。 默认为 TRUE。 将此选项设置为FALSE以处理单个线程中所有非线程安全操作 (例如,压缩)的请求。 | 
示例:将文本数据写入HDFS
此示例使用了示例:读取HDFS中的文本数据中的数据格式。
| 列名 | 数据类型 | 
|---|---|
| location | text | 
| month | text | 
| number_of_orders | int | 
| total_sales | float8 | 
在此示例中您还可以选择在该练习创建的 pxf_hdfs_textsimple Greenplum数据库外部表。.
步骤
执行以下步骤,使用与上述相同的数据模式创建Greenplum数据库可写外部表,其中一个表将使用压缩。您将使用PXFhdfs:text配置文件和默认的PXF服务器将数据写入基础HDFS目录。您还将创建一个单独的可读外部表,以读取您写入HDFS目录的数据。
- 使用上述数据格式创建Greenplum数据库可写外部表。 写入HDFS目录 - /data/pxf_examples/pxfwritable_hdfs_textsimple1。 使用逗号- ,作为分隔符创建表:- postgres=# CREATE WRITABLE EXTERNAL TABLE pxf_hdfs_writabletbl_1(location text, month text, num_orders int, total_sales float8) LOCATION ('pxf://data/pxf_examples/pxfwritable_hdfs_textsimple1?PROFILE=hdfs:text') FORMAT 'TEXT' (delimiter=',');- 您将 - FORMAT子句- delimiter的值指定为单个ascii逗号字符- ,。
- 通过在 - pxf_hdfs_writabletbl_1上调用SQL- INSERT命令,将一些单独的记录写入- pxfwritable_hdfs_textsimple1HDFS目录:- postgres=# INSERT INTO pxf_hdfs_writabletbl_1 VALUES ( 'Frankfurt', 'Mar', 777, 3956.98 ); postgres=# INSERT INTO pxf_hdfs_writabletbl_1 VALUES ( 'Cleveland', 'Oct', 3812, 96645.37 );
- (可选) 写入您在示例:读取HDFS中的文本数据创建的 - pxf_hdfs_textsimple表中的数据到- pxf_hdfs_writabletbl_1:- postgres=# INSERT INTO pxf_hdfs_writabletbl_1 SELECT * FROM pxf_hdfs_textsimple;
- 在另一个终端窗口,显示刚添加到HDFS的数据: - $ hdfs dfs -cat /data/pxf_examples/pxfwritable_hdfs_textsimple1/* Frankfurt,Mar,777,3956.98 Cleveland,Oct,3812,96645.37 Prague,Jan,101,4875.33 Rome,Mar,87,1557.39 Bangalore,May,317,8936.99 Beijing,Jul,411,11600.67- 因为您在创建可写外部表时使用了逗号 - ,作为分隔符, 这个字符是HDFS数据中每条记录的字段分隔符.
- Greenplum数据库不支持直接查询可写外部表。要查询刚刚添加到HDFS的数据, 你必须创建一个引用这个HDFS目录的Greenplum可读外部表: - postgres=# CREATE EXTERNAL TABLE pxf_hdfs_textsimple_r1(location text, month text, num_orders int, total_sales float8) LOCATION ('pxf://data/pxf_examples/pxfwritable_hdfs_textsimple1?PROFILE=hdfs:text') FORMAT 'CSV';- 在创建可读外部表时使用 - 'CSV'- FORMAT,因为您在创建可写外部表时使用逗号- ,作为分隔符,即- 'CSV'- FORMAT的默认分隔符。
- 查询可读外部表: - postgres=# SELECT * FROM pxf_hdfs_textsimple_r1 ORDER BY total_sales;- location | month | num_orders | total_sales -----------+-------+------------+------------- Rome | Mar | 87 | 1557.39 Frankfurt | Mar | 777 | 3956.98 Prague | Jan | 101 | 4875.33 Bangalore | May | 317 | 8936.99 Beijing | Jul | 411 | 11600.67 Cleveland | Oct | 3812 | 96645.37 (6 rows)- pxf_hdfs_textsimple_r1表包含您单独插入的记录, 以及执行可选步骤时- pxf_hdfs_textsimple表的完整内容。
- 创建第二个Greenplum数据库可写外部表, 这次使用Gzip压缩并使用冒号 - :作为分隔符:- postgres=# CREATE WRITABLE EXTERNAL TABLE pxf_hdfs_writabletbl_2 (location text, month text, num_orders int, total_sales float8) LOCATION ('pxf://data/pxf_examples/pxfwritable_hdfs_textsimple2?PROFILE=hdfs:text&COMPRESSION_CODEC=org.apache.hadoop.io.compress.GzipCodec') FORMAT 'TEXT' (delimiter=':');
- 通过直接写入 - pxf_hdfs_writabletbl_2表,将一些记录写入- pxfwritable_hdfs_textsimple2HDFS目录:- gpadmin=# INSERT INTO pxf_hdfs_writabletbl_2 VALUES ( 'Frankfurt', 'Mar', 777, 3956.98 ); gpadmin=# INSERT INTO pxf_hdfs_writabletbl_2 VALUES ( 'Cleveland', 'Oct', 3812, 96645.37 );
- 在另一个终端窗口中,显示您刚添加到HDFS的数据;使用 - hdfs dfs- -text选项以文本的形式查看压缩数据:- $ hdfs dfs -text /data/pxf_examples/pxfwritable_hdfs_textsimple2/* Frankfurt:Mar:777:3956.98 Cleveland:Oct:3812:96645.3- 请注意冒号 - :是此HDFS数据的字段分隔符。- 要从名为 - pxfwritable_hdfs_textsimple2的新创建的HDFS目录中查询数据,您可以创建一个Greenplum可读外部表并指定- FORMAT 'CSV' (delimiter=':')。