HAWQ 技术解析(九) —— 外部数据

本文介绍PXF框架如何实现HAWQ对HDFS、Hive等外部数据源的访问,涵盖PXF安装配置、访问HDFS文件、访问Hive数据等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、安装配置 PXF

二、PXF profile

三、访问 HDFS 文件

1. PXF 支持的 HDFS 文件格式

2. 查询外部 HDFS 数据

四、访问 Hive 数据

1. PXF 访问 Hive 的前提条件

2. PXF 支持的 Hive 文件格式

3. 数据类型映射

4. 准备示例数据

5. 使用 PXF 和 HCatalog 查询 Hive

6. 查询 Hive 外部表

(1)Hive Profile

(2)HiveText Profile

(3)HiveRC Profile

(4)访问 Parquet 格式的 Hive 表

7. 复杂数据类型

8. 访问 Hive 分区表

(1)使用 Hive Profile 访问同构分区数据

(2)使用 Hive Profile 访问异构分区数据

五、访问 JSON 数据

1. PXF 与 JSON 文件协同工作

(1)JSON 到 HAWQ 的数据类型映射

(2)JSON 文件读模式

2. 将 JSON 数据装载到 HDFS

3. 查询外部的 JSON 数据

六、向 HDFS 中写入数据

1. 写 PXF 外部表

2. 定制选项

3. 使用 HdfsTextSimple Profile 写数据

七、删除外部表


        HAWQ 不但可以读写自身系统中的表,而且能够访问 HDFS、Hive、HBase 等外部系统的数据,这是通过一个名为 PXF 的扩展框架实现的。大部分外部数据是以 HAWQ 外部表的形式进行访问的,但对于 Hive,除外部表方式,PXF 还能够与 HCatalog 结合直接查询 Hive 表。PXF 内建多个连接器,用户也可以按照 PXF API 创建自己的连接器,访问其他并行数据存储或处理引擎。

一、安装配置 PXF

        如果使用 Ambari 安装管理 HAWQ 集群,那么不需要执行任何手工命令行安装步骤,从 Ambari web 接口就可以安装所有需要的 PXF 插件。详细安装步骤参考“HAWQ 技术解析(二) —— 安装部署”。如果使用命令行安装 PXF,参见“Installing PXF from the Command Line”。PXF 相关的缺省安装目录和文件如表1 所示。

目录

描述

/usr/lib/pxf

PXF 库目录。

/etc/pxf/conf

PXF 配置目录,该目录下包含 pxf-public.classpath、pxf-private.classpath 及其他配置文件。

/var/pxf/pxf-service

PXF 服务实例所在目录。

/var/log/pxf

该目录包含 pxf-service.log 和所有 Tomcat 相关的日志文件。PXF 需要在主机上运行 Tomcat,用 Ambari 安装 PXF 时会自动安装 Tomcat,这些文件的属主是 pxf:pxf,对其他用户是只读的。

/var/run/pxf/catalina.pid

PXF Tomcat 容器的 PID 文件,存储进程号。

表1

        与安装一样,PXF 也可以使用 Ambari 的图形界面进行交互式配置,完成后重启 PXF 服务以使配置生效。手工配置步骤参考“Configuring PXF”,注意,手工配置需要修改所有集群主机上的相关配置文件,然后重启所有节点上的 PXF 服务。

二、PXF profile

        PXF profile 是一组通用元数据属性的集合,用于简化外部数据读写。PXF 自带多个内建的 profile,每个 profile 将一组元数据属性归于一类,使得对以下数据存储系统的访问更加容易:

  • HDFS 文件数据(读写)
  • Hive(只读)
  • HBase(只读)
  • JSON(只读)

        表2 说明了 PXF 的内建 profile 及其相关 Java 类,这些 profile 在 /etc/pxf/conf/pxf-profiles.xml 文件中定义。

Profile 

描述 

相关Java类 

 HdfsTextSimple

读写 HDFS 上的平面文本文件,每条记录由固定分隔符的一行构成。

org.apache.hawq.pxf.plugins.hdfs.HdfsDataFragmenter

org.apache.hawq.pxf.plugins.hdfs.LineBreakAccessor

org.apache.hawq.pxf.plugins.hdfs.StringPassResolver

 HdfsTextMulti

从 HDFS 上的平面文件中读取具有固定分隔符的记录,每条记录由一行或多行(记录中包含换行符)构成。此 profile 是不可拆分的(非并行),比 HdfsTextSimple 读取慢。

org.apache.hawq.pxf.plugins.hdfs.HdfsDataFragmenter

org.apache.hawq.pxf.plugins.hdfs.QuotedLineBreakAccessor

org.apache.hawq.pxf.plugins.hdfs.StringPassResolver

 Hive

读 Hive 表,支持 text、RC、ORC、Sequence 或 Parquet 存储格式。

org.apache.hawq.pxf.plugins.hive.HiveDataFragmenter

org.apache.hawq.pxf.plugins.hive.HiveAccessor

org.apache.hawq.pxf.plugins.hive.HiveResolver

org.apache.hawq.pxf.plugins.hive.HiveMetadataFetcher

org.apache.hawq.pxf.service.io.GPDBWritable

 HiveRC

优化读取 RCFile 存储格式的 Hive 表,必须指定 DELIMITER 参数。

org.apache.hawq.pxf.plugins.hive.HiveInputFormatFragmenter

org.apache.hawq.pxf.plugins.hive.HiveRCFileAccessor

org.apache.hawq.pxf.plugins.hive.HiveColumnarSerdeResolver

org.apache.hawq.pxf.plugins.hive.HiveMetadataFetcher

org.apache.hawq.pxf.service.io.Text

 HiveORC

优化读取 ORCFile 存储格式的 Hive 表。

org.apache.hawq.pxf.plugins.hive.HiveInputFormatFragmenter

org.apache.hawq.pxf.plugins.hive.HiveORCAccessor

org.apache.hawq.pxf.plugins.hive.HiveORCSerdeResolver

org.apache.hawq.pxf.plugins.hive.HiveMetadataFetcher

org.apache.hawq.pxf.service.io.GPDBWritable

 HiveText

优化读取 TextFile 存储格式的 Hive 表,必须指定 DELIMITER 参数。

org.apache.hawq.pxf.plugins.hive.HiveInputFormatFragmenter

org.apache.hawq.pxf.plugins.hive.HiveLineBreakAccessor

org.apache.hawq.pxf.plugins.hive.HiveStringPassResolver

org.apache.hawq.pxf.plugins.hive.HiveMetadataFetcher

org.apache.hawq.pxf.service.io.Text

 HBase

读取 HBase 数据存储引擎。

org.apache.hawq.pxf.plugins.hbase.HBaseDataFragmenter

org.apache.hawq.pxf.plugins.hbase.HBaseAccessor

org.apache.hawq.pxf.plugins.hbase.HBaseResolver

 Avro

读取 Avro 文件。

org.apache.hawq.pxf.plugins.hdfs.HdfsDataFragmenter

org.apache.hawq.pxf.plugins.hdfs.AvroFileAccessor

org.apache.hawq.pxf.plugins.hdfs.AvroResolver

JSON

读取 HDFS 上的 JSON 文件。

org.apache.hawq.pxf.plugins.hdfs.HdfsDataFragmenter

org.apache.hawq.pxf.plugins.json.JsonAccessor

org.apache.hawq.pxf.plugins.json.JsonResolver

表2

三、访问 HDFS 文件

        HDFS 是 Hadoop 应用的主要分布式存储机制,PXF 的 HDFS 插件用于读取存储在 HDFS 文件中的数据,支持具有固定分隔符的文本和 Avro 两种文件格式。在使用 PXF 访问 HDFS 文件前,确认已经在集群所有节点上安装了 PXF HDFS 插件(Ambari 会自动安装),并授予了 HAWQ 用户(典型的是 gpadmin)对 HDFS 文件相应的读写权限。

1. PXF 支持的 HDFS 文件格式

        PXF HDFS 插件支持对以下两种文件格式的读取:

  • comma-separated value(.csv)或其他固定分隔符的平面文本文件。
  • 由 JSON 定义的、基于 Schema 的 Avro 文件格式。

        PXF HDFS 插件包括以下 Profile 支持上面的两类文件:

  • HdfsTextSimple - 单行文本文件
  • HdfsTextMulti - 内嵌换行符的多行文本文件
  • Avro - Avro 文件

2. 查询外部 HDFS 数据

        HAWQ 通过外部表的形式访问 HDFS 文件。下面是创建一个 HDFS 外部表的语法。

CREATE EXTERNAL TABLE <table_name> 
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<host>[:<port>]/<path-to-hdfs-file>
    ?PROFILE=HdfsTextSimple|HdfsTextMulti|Avro[&<custom-option>=<value>[...]]')
FORMAT '[TEXT|CSV|CUSTOM]' (<formatting-properties>);

        CREATE EXTERNAL TABLE 语句中使用的各个关键字和相应值的描述如表3 所示。

关键字

<host>[:<port>]

HDFS NameNode 主机名、端口。

<path-to-hdfs-file>

HDFS 文件路径。

PROFILE

PROFILE 关键字指定为 HdfsTextSimple、HdfsTextMulti 或 Avro 之一。

<custom-option>

与特定 PROFILE 对应的定制选项。

FORMAT 'TEXT'

当 <path-to-hdfs-file> 指向一个单行固定分隔符的平面文件时,使用该关键字。

FORMAT 'CSV'

当 <path-to-hdfs-file> 指向一个单行或多行的逗号分隔值(CSV)平面文件时,使用该关键字。

FORMAT 'CUSTOM'

Avro 文件使用该关键字。Avro 'CUSTOM' 格式只支持内建的(formatter='pxfwritable_import')格式属性。

<formatting-properties>

与特定 PROFILE 对应的格式属性。

表3

        下面是几个 HAWQ 访问 HDFS 文件的例子。

(1)使用 HdfsTextSimple Profile

        HdfsTextSimple Profile 用于读取一行表示一条记录的平面文本文件或 CSV 文件,支持的 <formatting-properties> 是 delimiter,用来指定文件中每条记录的字段分隔符。

        为 PXF 创建一个 HDFS 目录。

su - hdfs
hdfs dfs -mkdir -p /data/pxf_examples
hdfs dfs -chown -R gpadmin:gpadmin /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

        使用 HdfsTextSimple profile 创建一个可从 pxf_hdfs_simple.txt 文件查询数据的 HAWQ 外部表。delimiter=e',' 中的 e 表示转义,就是说如果记录正文中含有逗号,需要用 \ 符号进行转义。

su - gpadmin 
psql -d db1
db1=# create external table pxf_hdfs_textsimple(location text, month text, num_orders int, total_sales float8)
db1-#             location ('pxf://hdp1:51200/data/pxf_examples/pxf_hdfs_simple.txt?profile=hdfstextsimple')
db1-#           format 'text' (delimiter=e',');
CREATE EXTERNAL TABLE
db1=# 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)

        用 CSV 格式创建第二个外部表。当指定格式为‘CSV’时,逗号是缺省分隔符,不再需要使用 delimiter 说明。

db1=# create external table pxf_hdfs_textsimple_csv(location text, month text, num_orders int, total_sales float8)
db1-#             location ('pxf://hdp1:51200/data/pxf_examples/pxf_hdfs_simple.txt?profile=hdfstextsimple')
db1-#           format 'csv';
CREATE EXTERNAL TABLE
db1=# select * from pxf_hdfs_textsimple_csv; 
 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)

(2)使用 HdfsTextMulti Profile

        HdfsTextMulti profile 用于读取一条记录中含有换行符的平面文本文件。因为 PXF 将换行符作为行分隔符,所以当数据中含有换行符时需要用 HdfsTextMulti 进行特殊处理。HdfsTextMulti Profile 支持的 <formatting-properties> 是 delimiter,用来指定文件中每条记录的字段分隔符。

        创建一个平面文本文件。

vim /tmp/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 上。

su - hdfs
hdfs dfs -put /tmp/pxf_hdfs_multi.txt /data/pxf_examples/

        使用 HdfsTextMulti profile 创建一个可从 pxf_hdfs_multi.txt 文件查询数据的外部表,指定分隔符是冒号。

db1=# create external table pxf_hdfs_textmulti(address text, month text, year int)
db1-#             location ('pxf://hdp1:51200/data/pxf_examples/pxf_hdfs_multi.txt?profile=hdfstextmulti')
db1-#           format 'csv' (delimiter=e':');
CREATE EXTERNAL TABLE
db1=# 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)

(3)Avro Profile

        参见"Avro Profile"。

(4)访问 HDFS HA 集群中的文件

        为了访问 HDFS HA 集群中的外部数据,将 CREATE EXTERNAL TABLE LOCATION 子句由 <host>[:<port>] 修改为 <HA-nameservice>。

gpadmin=# create external table pxf_hdfs_textmulti_ha (address text, month text, year int)
            location ('pxf://mycluster/data/pxf_examples/pxf_hdfs_multi.txt?profile=hdfstextmulti')
          format 'csv' (delimiter=e':');
gpadmin=# select * from pxf_hdfs_textmulti_ha;

        查询结果如图1 所示。

图1

四、访问 Hive 数据

        Hive 是 Hadoop 的分布式数据仓库框架,支持多种文件格式,如 CVS、RC、ORC、parquet 等,PXF 的 Hive 插件用于读取存储在 Hive 表中的数据。PXF 提供两种方式查询 Hive 表:

  • 通过整合 PXF 与 HCatalog 直接查询。
  • 通过外部表查询。

1. PXF 访问 Hive 的前提条件

        在使用 PXF 访问 Hive 前,确认满足以下前提条件:

  • 在 HAWQ 和 HDFS 集群的所有节点上(master、segment、NameNode、DataNode)安装了 PXF HDFS 插件。
  • 在 HAWQ 和 HDFS 集群的所有节点上安装了 PXF Hive 插件。
  • 如果配置了 Hadoop HA,PXF 也必须安装在所有运行 NameNode 服务的 HDFS 节点上。
  • 所有 PXF 节点上都安装了 Hive 客户端。
  • 集群所有节点上都安装了 Hive JAR 文件目录和 conf 目录。
  • 已经测试了 PXF 访问 HDFS。
  • 在集群中的一台主机上运行 Hive Metastore 服务。
  • 在 NameNode 上的 hive-site.xml 文件中设置了 hive.metastore.uris 属性。

        看似条件不少,但是如果使用 Ambari 安装管理 HAWQ 集群,并安装了 Hadoop 相关服务,则所有这些前置条件都已自动配置好,不需要任何手工配置。

2. PXF 支持的 Hive 文件格式

        PXF Hive 插件支持的 Hive 文件格式及其访问这些格式对应的 profile 如表4 所示。

文件格式

描述

Profile

TextFile

逗号、tab或空格分隔的平面文件格式或JSON格式。

Hive、HiveText

SequenceFile

二进制键值对组成的平面文件。

Hive

RCFile

记录由键值对组成的列数据,具有行高压缩率。

Hive、HiveRC

ORCFile

优化的列式存储,减小数据大小。

Hive

Parquet

压缩的列式存储。

Hive

Avro

基于schema的、由JSON所定义的序列化格式。

Hive

表4

3. 数据类型映射

        为了在 HAWQ 中表示 Hive 数据,需要将使用 Hive 私有数据类型的数据值映射为等价的 HAWQ 类型值。表5 是对 Hive 私有数据类型的映射规则汇总。

Hive 数据类型

HAWQ 数据类型

boolean

bool

int

int4

smallint

int2

tinyint

int2

bigint

int8

float

float4

double

float8

string

text

binary

bytea

timestamp

timestamp

表5

        除简单类型外,Hive 还支持 array、struct、map 等复杂数据类型,由于 HAWQ 原生不支持这些类型,PXF 将它们统一映射为 text 类型。可以创建 HAWQ 函数或使用应用程序抽取复杂数据类型子元素的数据。

        下面是一些 HAWQ 访问 Hive 表的例子。

4. 准备示例数据

(1)准备数据文件

        添加如下记录,用逗号分隔字段。

vi /tmp/pxf_hive_datafile.txt
Prague,Jan,101,4875.33
Rome,Mar,87,1557.39
Bangalore,May,317,8936.99
Beijing,Jul,411,11600.67
San Francisco,Sept,156,6846.34
Paris,Nov,159,7134.56
San Francisco,Jan,113,5397.89
Prague,Dec,333,9894.77
Bangalore,Jul,271,8320.55
Beijing,Dec,100,4248.41

(2)创建文本格式的 Hive 表 sales_info

create database test;
use test;
create table sales_info (location string, month string,
        number_of_orders int, total_sales double)
        row format delimited fields terminated by ','
        stored as textfile;

(3)向 sales_info 表装载数据

load data local inpath '/tmp/pxf_hive_datafile.txt' into table sales_info;

(4)查询 sales_info 表数据验证装载数据是否成功

select * from sales_info;

(5)确认 sales_info 表在 HDFS 上的位置

        在创建 HAWQ 外部表时需要用到该信息。

describe extended sales_info;
...
location:hdfs://mycluster/apps/hive/warehouse/test.db/sales_info
...

5. 使用 PXF 和 HCatalog 查询 Hive

        HAWQ 可以获取存储在 HCatalog 中的元数据,通过 HCatalog 直接访问 Hive 表,而不用关心 Hive 表对应的底层文件存储格式。HCatalog 建立在 Hive metastore 之上,包含 Hive 的 DDL 语句。使用这种方式的好处是:

  • 不须要知道 Hive 表结构。
  • 不须要手工输入 Hive 表的位置与格式信息。
  • 如果表的元数据改变,HCatalog 自动提供更新后的元数据,这是使用 PXF 静态外部表方式无法做到的。

        图2 所示 HAWQ 如何使用 HCatalog 查询 Hive 表。

图2

  1. HAWQ 使用 PXF 从 HCatalog 查询表的元数据。
  2. HAWQ 用查询到的元数据创建一个内存目录表,如果一个查询中多次引用了同一个表,内存目录表可以减少对外部 HCatalog 的调用次数。
  3. PXF 使用内存目录表的元数据信息查询 Hive 表,查询结束后,内存目录表将被删除。

        如果使用 Ambari 安装管理 HAWQ,并且已经启动了 Hive 服务,则不需要任何额外配置,就可以查询 Hive 表。

db1=# select * from hcatalog.test.sales_info;
   location    | month | number_of_orders | total_sales 
---------------+-------+------------------+-------------
 Prague        | Jan   |              101 |     4875.33
 Rome          | Mar   |               87 |     1557.39
 Bangalore     | May   |              317 |     8936.99
 Beijing       | Jul   |              411 |    11600.67
 San Francisco | Sept  |              156 |     6846.34
 Paris         | Nov   |              159 |     7134.56
 San Francisco | Jan   |              113 |     5397.89
 Prague        | Dec   |              333 |     9894.77
 Bangalore     | Jul   |              271 |     8320.55
 Beijing       | Dec   |              100 |     4248.41
(10 rows)

        获取 Hive 表的字段和数据类型映射。

db1=# \d+ hcatalog.test.sales_info;
    PXF Hive Table "test.sales_info"
      Column      |  Type  | Source type 
------------------+--------+-------------
 location         | text   | string
 month            | text   | string
 number_of_orders | int4   | int
 total_sales      | float8 | double

        可以使用通配符获取所有 Hive 库表的信息。

\d+ hcatalog.test.*;
\d+ hcatalog.*.*;

        还可以使用 pxf_get_item_fields 函数获得 Hive 表的描述信息,该函数目前仅支持 Hive profile。

db1=# select * from pxf_get_item_fields('hive','test.sales_info');
 path |  itemname  |    fieldname     | fieldtype | sourcefieldtype 
------+------------+------------------+-----------+-----------------
 test | sales_info | location         | text      | string
 test | sales_info | month            | text      | string
 test | sales_info | number_of_orders | int4      | int
 test | sales_info | total_sales      | float8    | double
(4 rows)

        pxf_get_item_fields 函数同样也支持通配符。

select * from pxf_get_item_fields('hive','test.*');
select * from pxf_get_item_fields('hive','*.*');

6. 查询 Hive 外部表

        使用外部表方式需要标识适当的 profile。PXF Hive 插件支持三种 Hive 相关的 profile,Hive、HiveText 和 HiveRC。HiveText 和 HiveRC 分别针对 TEXT 和 RC 文件格式做了特别优化,而 Hive profile 可用于所有 PXF 支持的 Hive 文件存储类型。当底层 Hive 表由多个分区组成,并且分区使用了不同的文件格式,需要使用 Hive profile。

        以下语法创建一个 HAWQ 的 Hive 外部表:

CREATE EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<host>[:<port>]/<hive-db-name>.<hive-table-name>
    ?PROFILE=Hive|HiveText|HiveRC[&DELIMITER=<delim>'])
FORMAT 'CUSTOM|TEXT' (formatter='pxfwritable_import' | delimiter='<delim>')

        CREATE EXTERNAL TABLE 语句中 Hive 插件使用关键字和相应值的描述如表6 所示。

关键字

<host>[:]

HDFS NameNode 主机名、端口号

<hive-db-name>

Hive 数据库名,如果忽略,缺省是 defaults。

<hive-table-name>

Hive 表名。

PROFILE

必须是 Hive、HiveText 或 HiveRC 之一。

DELIMITER

指定字段分隔符,必须是单个 ascii 字符或相应字符的十六进制表示。

FORMAT (Hive profile)

必须指定为 CUSTOM,仅支持内建的 pxfwritable_import 格式属性。

FORMAT (HiveText and HiveRC profiles)

必须指定为 TEXT,并再次指定字段分隔符。

表6

(1)Hive Profile

        Hive profile 适用于任何 PXF 支持的 Hive 文件存储格式,它实际上是为底层文件存储类型选择最优的 Hive* profile。

db1=# create external table salesinfo_hiveprofile(location text, month text, num_orders int, total_sales float8)
db1-#             location ('pxf://hdp1:51200/test.sales_info?profile=hive')
db1-#           format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# 
db1=# select * from salesinfo_hiveprofile;
   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
 San Francisco | Sept  |        156 |     6846.34
 Paris         | Nov   |        159 |     7134.56
 San Francisco | Jan   |        113 |     5397.89
 Prague        | Dec   |        333 |     9894.77
 Bangalore     | Jul   |        271 |     8320.55
 Beijing       | Dec   |        100 |     4248.41
(10 rows)

        注意外部表和 Hcatalog 查询计划的区别,如图3 所示。

图3

        外部表查询使用了全部 24 个虚拟段,而 Hcatalog 查询只使用了 1 个虚拟段,显然外部表更加有效地利用了资源。

(2)HiveText Profile

        使用 HiveText profile 时,必须在 LOCATION 和 FORMAT 两个子句中都指定分隔符选项。

db1=# create external table salesinfo_hivetextprofile(location text, month text, num_orders int, total_sales float8)
db1-# location ('pxf://hdp1:51200/test.sales_info?profile=hivetext&delimiter=,')
db1-# format 'text' (delimiter=e',');
CREATE EXTERNAL TABLE
db1=# select * from salesinfo_hivetextprofile where location='Beijing';
 location | month | num_orders | total_sales 
----------+-------+------------+-------------
 Beijing  | Jul   |        411 |    11600.67
 Beijing  | Dec   |        100 |     4248.41
(2 rows)

(3)HiveRC Profile

        建立一个 rcfile 格式的 Hive 表,并插入数据。

create table sales_info_rcfile (location string, month string,
        number_of_orders int, total_sales double)
      row format delimited fields terminated by ','
      stored as rcfile;
	  
insert into table sales_info_rcfile select * from sales_info;

        查询 Hive 表。

db1=# create external table salesinfo_hivercprofile(location text, month text, num_orders int, total_sales float8)
db1-#              location ('pxf://hdp1:51200/test.sales_info_rcfile?profile=hiverc&delimiter=,')
db1-#            format 'text' (delimiter=e',');
CREATE EXTERNAL TABLE
db1=# 
db1=# select location, total_sales from salesinfo_hivercprofile;
   location    | total_sales 
---------------+-------------
 Prague        |     4875.33
 Rome          |     1557.39
 Bangalore     |     8936.99
 Beijing       |    11600.67
 San Francisco |     6846.34
 Paris         |     7134.56
 San Francisco |     5397.89
 Prague        |     9894.77
 Bangalore     |     8320.55
 Beijing       |     4248.41
(10 rows)

(4)访问 Parquet 格式的 Hive 表

        PXF Hive profile 支持分区或非分区的 Parquet 存储格式。建立一个 Parquet 格式的 Hive 表,并插入数据。

create table sales_info_parquet (location string, month string,
        number_of_orders int, total_sales double)
        stored as parquet;

insert into sales_info_parquet select * from sales_info;

        查询 Hive 表。

db1=# create external table salesinfo_parquet (location text, month text, num_orders int, total_sales float8)
db1-#     location ('pxf://hdp1:51200/test.sales_info_parquet?profile=hive')
db1-#     format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# 
db1=# select * from salesinfo_parquet;
   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
 San Francisco | Sept  |        156 |     6846.34
 Paris         | Nov   |        159 |     7134.56
 San Francisco | Jan   |        113 |     5397.89
 Prague        | Dec   |        333 |     9894.77
 Bangalore     | Jul   |        271 |     8320.55
 Beijing       | Dec   |        100 |     4248.41
(10 rows)

7. 复杂数据类型

(1)准备数据文件,添加如下记录,用逗号分隔字段,第三个字段是 array 类型,第四个字段是 map 类型。

vi /tmp/pxf_hive_complex.txt
3,Prague,1%2%3,zone:euro%status:up
89,Rome,4%5%6,zone:euro
400,Bangalore,7%8%9,zone:apac%status:pending
183,Beijing,0%1%2,zone:apac
94,Sacramento,3%4%5,zone:noam%status:down
101,Paris,6%7%8,zone:euro%status:up
56,Frankfurt,9%0%1,zone:euro
202,Jakarta,2%3%4,zone:apac%status:up
313,Sydney,5%6%7,zone:apac%status:pending
76,Atlanta,8%9%0,zone:noam%status:down

(2)建立 Hive 表

create table table_complextypes( index int, name string, intarray array<int>, propmap map<string, string>)
         row format delimited fields terminated by ','
         collection items terminated by '%'
         map keys terminated by ':'
         stored as textfile;

(3)向 Hive 表装载数据

load data local inpath '/tmp/pxf_hive_complex.txt' into table table_complextypes;

(4)查询 Hive 表,验证数据正确导入

select * from table_complextypes;

(5)建立 Hive 外部表并查询数据

db1=# create external table complextypes_hiveprofile(index int, name text, intarray text, propmap text)
db1-#              location ('pxf://hdp1:51200/test.table_complextypes?profile=hive')
db1-#            format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# select * from complextypes_hiveprofile;
 index |    name    | intarray |              propmap               
-------+------------+----------+------------------------------------
     3 | Prague     | [1,2,3]  | {"zone":"euro","status":"up"}
    89 | Rome       | [4,5,6]  | {"zone":"euro"}
   400 | Bangalore  | [7,8,9]  | {"zone":"apac","status":"pending"}
   183 | Beijing    | [0,1,2]  | {"zone":"apac"}
    94 | Sacramento | [3,4,5]  | {"zone":"noam","status":"down"}
   101 | Paris      | [6,7,8]  | {"zone":"euro","status":"up"}
    56 | Frankfurt  | [9,0,1]  | {"zone":"euro"}
   202 | Jakarta    | [2,3,4]  | {"zone":"apac","status":"up"}
   313 | Sydney     | [5,6,7]  | {"zone":"apac","status":"pending"}
    76 | Atlanta    | [8,9,0]  | {"zone":"noam","status":"down"}
(10 rows)

        可以看到,复杂数据类型都被简单地转化为 HAWQ 的 TEXT 类型。

8. 访问 Hive 分区表

        PXF Hive 插件支持 Hive 的分区特性与目录结构,并且提供了所谓的分区过滤下推功能,可以利用 Hive 的分区消除特性,以降低网络流量和 I/O 负载。PXF 的分区过滤下推与 MySQL 的索引条件下推(Index Condition Pushdown,ICP)概念上类似,都是将过滤条件下推至更底层的存储上,以提高性能。

        为了利用 PXF 的分区过滤下推功能,查询的 where 子句中应该只使用分区字段,否则,PXF 忽略分区过滤,过滤将在 HAWQ 端执行,影响查询性能。PXF 的 Hive 插件只对分区键执行过滤下推。

        分区过滤下推缺省是启用的:

db1=# show pxf_enable_filter_pushdown;
 pxf_enable_filter_pushdown 
----------------------------
 on
(1 row)

(1)使用 Hive Profile 访问同构分区数据

        创建 Hive 表并装载数据。

create table sales_part (name string, type string, supplier_key int, price double)
        partitioned by (delivery_state string, delivery_city string)
        row format delimited fields terminated by ',';

insert into table sales_part partition(delivery_state = 'CALIFORNIA', delivery_city = 'Fresno') 
values ('block', 'widget', 33, 15.17);
insert into table sales_part partition(delivery_state = 'CALIFORNIA', delivery_city = 'Sacramento') 
values ('cube', 'widget', 11, 1.17);
insert into table sales_part partition(delivery_state = 'NEVADA', delivery_city = 'Reno') 
values ('dowel', 'widget', 51, 31.82);
insert into table sales_part partition(delivery_state = 'NEVADA', delivery_city = 'Las Vegas') 
values ('px49', 'pipe', 52, 99.82);

        查询 sales_part 表。

select * from sales_part;

        检查 sales_part 表在 HDFS 上的目录结构。

sudo -u hdfs hdfs dfs -ls -R /apps/hive/warehouse/test.db/sales_part

        建立 PXF 外部表并查询数据。

db1=# create external table pxf_sales_part(
db1(#              item_name text, item_type text, 
db1(#              supplier_key integer, item_price double precision, 
db1(#              delivery_state text, delivery_city text)
db1-#            location ('pxf://hdp1:51200/test.sales_part?profile=hive')
db1-#            format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# select * from pxf_sales_part;
 item_name | item_type | supplier_key | item_price | delivery_state | delivery_city 
-----------+-----------+--------------+------------+----------------+---------------
 block     | widget    |           33 |      15.17 | CALIFORNIA     | Fresno
 dowel     | widget    |           51 |      31.82 | NEVADA         | Reno
 cube      | widget    |           11 |       1.17 | CALIFORNIA     | Sacramento
 px49      | pipe      |           52 |      99.82 | NEVADA         | Las Vegas
(4 rows)

        执行一个非过滤下推的查询。

db1=# select * from pxf_sales_part where delivery_city = 'Sacramento' and item_name = 'cube';
 item_name | item_type | supplier_key | item_price | delivery_state | delivery_city 
-----------+-----------+--------------+------------+----------------+---------------
 cube      | widget    |           11 |       1.17 | CALIFORNIA     | Sacramento
(1 row)

        该查询会利用 Hive 过滤 delivery_city='Sacramento' 的分区,但 item_name 上的过滤条件不会下推至 Hive,因为它不是分区列。当所有 Sacramento 分区的数据传到 HAWQ 后,在 HAWQ 端执行 item_name 的过滤。

        执行一个过滤下推的查询。

db1=# select * from pxf_sales_part where delivery_state = 'CALIFORNIA';
 item_name | item_type | supplier_key | item_price | delivery_state | delivery_city 
-----------+-----------+--------------+------------+----------------+---------------
 cube      | widget    |           11 |       1.17 | CALIFORNIA     | Sacramento
 block     | widget    |           33 |      15.17 | CALIFORNIA     | Fresno
(2 rows)

(2)使用 Hive Profile 访问异构分区数据

        一个 Hive 表中的不同分区可能有不同的存储格式,PXF Hive profile 也支持这种情况。

        建立 Hive 表。

$ HADOOP_USER_NAME=hdfs hive
create external table hive_multiformpart( location string, month string, number_of_orders int, total_sales double)
        partitioned by( year string )
        row format delimited fields terminated by ',';

        记下 sales_info 和 sales_info_rcfile 表在 HDFS 中的位置。

describe extended sales_info;
describe extended sales_info_rcfile;

        在我的环境中两个表的目录分别是:

location:hdfs://mycluster/apps/hive/warehouse/test.db/sales_info
location:hdfs://mycluster/apps/hive/warehouse/test.db/sales_info_rcfile

        给 hive_multiformpart 表增加两个分区,位置分别指向 sales_info 和 sales_info_rcfile。

alter table hive_multiformpart add partition (year = '2013') location 'hdfs://mycluster/apps/hive/warehouse/test.db/sales_info';
alter table hive_multiformpart add partition (year = '2016') location 'hdfs://mycluster/apps/hive/warehouse/test.db/sales_info_rcfile';

        显式标识与 sales_info_rcfile 表对应分区的文件格式。

alter table hive_multiformpart partition (year='2016') set fileformat rcfile;

        此时查看两个分区的存储格式可以看到,sales_info 表对应的分区使用的是缺省的 TEXTFILE 格式,而 sales_info_rcfile 表对应的分区是 RCFILE 格式,分别如图4、图5 所示。

show partitions hive_multiformpart;
desc formatted hive_multiformpart partition(year=2013);  
desc formatted hive_multiformpart partition(year=2016); 

图4

图5 

        使用 Hcatalog 方式查询 hive_multiformpart 表。

db1=# select * from hcatalog.test.hive_multiformpart;
   location    | month | number_of_orders | total_sales | year 
---------------+-------+------------------+-------------+------
...
 Prague        | Dec   |              333 |     9894.77 | 2013
 Bangalore     | Jul   |              271 |     8320.55 | 2013
 Beijing       | Dec   |              100 |     4248.41 | 2013
 Prague        | Jan   |              101 |     4875.33 | 2016
 Rome          | Mar   |               87 |     1557.39 | 2016
 Bangalore     | May   |              317 |     8936.99 | 2016
 ...
(20 rows)

        使用外部表方式查询 hive_multiformpart 表。

db1=# create external table pxf_multiformpart(location text, month text, num_orders int, total_sales float8, year text)
db1-#              location ('pxf://hdp1:51200/test.hive_multiformpart?profile=hive')
db1-#            format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# select * from pxf_multiformpart;
   location    | month | num_orders | total_sales | year 
---------------+-------+------------+-------------+------
... 
 Prague        | Dec   |        333 |     9894.77 | 2013
 Bangalore     | Jul   |        271 |     8320.55 | 2013
 Beijing       | Dec   |        100 |     4248.41 | 2013
 Prague        | Jan   |        101 |     4875.33 | 2016
 Rome          | Mar   |         87 |     1557.39 | 2016
 Bangalore     | May   |        317 |     8936.99 | 2016
...
(20 rows)

db1=# select sum(num_orders) from pxf_multiformpart where month='Dec' and year='2013';
 sum 
-----
 433
(1 row)

五、访问 JSON 数据

        PXF 的 JSON 插件用于读取存储在 HDFS 上的 JSON 文件,支持 N 层嵌套。为了使用 HAWQ 访问 JSON 数据,必须将 JSON 文件存储在 HDFS 上,并从 HDFS 数据存储创建外部表。在使用 PXF 访问 JSON 文件前,确认满足以下前提条件:

  • 已经在集群所有节点上安装了 HDFS 插件(Ambari 会自动安装)。
  • 已经在集群所有节点上安装了 JSON 插件(Ambari 会自动安装)。
  • 已经测试了 PXF 对 HDFS 的访问。

1. PXF 与 JSON 文件协同工作

        JSON 是一种基于文本的数据交换格式,其数据通常存储在一个以 .json 为后缀的文件中。一个 .json 文件包含一组对象的集合,一个 JSON 对象是一组无序的名/值对,值可以是字符串、数字、true、false、null,或者一个对象或数组,对象和数组可以嵌套。例如,下面是一个 JSON 数据文件的内容:

{
  "created_at":"MonSep3004:04:53+00002013",
  "id_str":"384529256681725952",
  "user": {
    "id":31424214,
     "location":"COLUMBUS"
  },
  "coordinates":null
}

(1)JSON 到 HAWQ 的数据类型映射

        为了在 HAWQ 中表示 JSON 数据,需要将使用私有数据类型的 JSON 值映射为等价的 HAWQ 数据类型值。表7 是对 JSON 数据映射规则的总结。

JSON 数据类型

HAWQ 数据类型

integer、float、string、boolean

使用对应的 HAWQ 内建数据类型(integer、real、double precision、char、varchar、text、boolean)

Array

使用 [] 标识一个特定数组中具有私有数据类型成员的下标。

Object

使用 . 点标识符指定每个级别的具有私有数据类型的嵌套成员。

表7

(2)JSON 文件读模式

        PXF 的 JSON 插件用两个模式之一读取数据。缺省模式是每行一个完整的 JSON 记录,同时也支持对多行构成的 JSON 记录的读操作。下面是每种读模式的例子,示例 schema 包含数据列的名称和数据类型如下:

  • “created_at” - text
  • “id_str” - text
  • “user” - object(“id” - integer,“location” - text)
  • “coordinates” - object(“type” - text,“values” - array(integer))

        例1 - 每行一条 JSON 记录的读模式:

{"created_at":"FriJun0722:45:03+00002013","id_str":"343136551322136576","user":{"id":395504494,"location":"NearCornwall"},"coordinates":{"type":"Point","values": [ 6, 50 ]}},
{"created_at":"FriJun0722:45:02+00002013","id_str":"343136547115253761","user":{"id":26643566,"location":"Austin,Texas"}, "coordinates": null},
{"created_at":"FriJun0722:45:02+00002013","id_str":"343136547136233472","user":{"id":287819058,"location":""}, "coordinates": null}

        例2 - 多行 JSON 记录读模式:

{
  "root":[
    {
      "record_obj":{
        "created_at":"MonSep3004:04:53+00002013",
        "id_str":"384529256681725952",
        "user":{
          "id":31424214,
          "location":"COLUMBUS"
        },
        "coordinates":null
      },
      "record_obj":{
        "created_at":"MonSep3004:04:54+00002013",
        "id_str":"384529260872228864",
        "user":{
          "id":67600981,
          "location":"KryberWorld"
        },
        "coordinates":{
          "type":"Point",
          "values":[
             8,
             52
          ]
        }
      }
    }
  ]
}

        下面从 PXF 的 JSON 外部表查询上面的示例数据。

2. 将 JSON 数据装载到 HDFS

        PXF 的 JSON 插件读取存储在 HDFS 中的 JSON 文件,因此在 HAWQ 查询 JSON 数据前,必须先将 JSON 文件传到 HDFS 上。将前面的单行和多行 JSON 记录分别保存到 singleline.json 和 multiline.json 文件中,而且确保 JSON 文件中没有空行,然后将文件传到 HDFS。

su - hdfs
hdfs dfs -mkdir /user/data
hdfs dfs -chown -R gpadmin:gpadmin /user/data
hdfs dfs -put singleline.json /user/data
hdfs dfs -put multiline.json /user/data

        文件传到 HDFS 后,就可以通过 HAWQ 查询 JSON 数据。

3. 查询外部的 JSON 数据

        使用下面的语法创建一个表示 JSON 数据的 HAWQ 外部表。

CREATE EXTERNAL TABLE <table_name> 
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ( 'pxf://<host>[:<port>]/<path-to-data>?PROFILE=Json[&IDENTIFIER=<value>]' )
      FORMAT 'CUSTOM' ( FORMATTER='pxfwritable_import' );

        CREATE EXTERNAL TABLE 语句中使用的各个关键字和相应值的描述如表8 所示。

关键字

<host>[:<port>]

HDFS NameNode 主机名、端口。

PROFILE

PROFILE 关键字必须指定为 Json。

IDENTIFIER

只有当 JSON 文件是多行记录格式时,LOCATION 字符串中才包含 IDENTIFIER 关键字及其对应的值。<value>应该标识用以确定一个返回的 JSON 对象的成员名称,例如上面的示例2 中,应该指定 &IDENTIFIER=created_at。

FORMAT

FORMAT 子句必须指定为 CUSTOM。

FORMATTER

JSON 'CUSTOM'格式只支持内建的'pxfwritable_import'格式属性。

表8

        创建一个基于单行记录的 JSON 外部表。

create external table sample_json_singleline_tbl(
  created_at text,
  id_str text,
  text text,
  "user.id" integer,
  "user.location" text,
  "coordinates.values[0]" integer,
  "coordinates.values[1]" integer
)
location('pxf://hdp1:51200/user/data/singleline.json?profile=json')
format 'custom' (formatter='pxfwritable_import');
select * from sample_json_singleline_tbl;

        查询结果如图6 所示。

图6

        注意,原来 JSON 中的嵌套数据都被平面化展开。在查询结果中,使用 . 访问嵌套 user 对象(user.id和user.location),使用 [] 访问 coordinates.values 数组的元素(coordinates.values[0] 和 coordinates.values[1])。

        多行记录的 JSON 外部表与单行的类似,只是需要指定 identifier,指定标识记录的键。

db1=# create external table sample_json_multiline_tbl(
db1(#   created_at text,
db1(#   id_str text,
db1(#   text text,
db1(#   "user.id" integer,
db1(#   "user.location" text,
db1(#   "coordinates.values[0]" integer,
db1(#   "coordinates.values[1]" integer
db1(# )
db1-# location('pxf://hdp1:51200/user/data/multiline.json?profile=json&identifier=created_at')
db1-# format 'custom' (formatter='pxfwritable_import');
CREATE EXTERNAL TABLE
db1=# select * from sample_json_multiline_tbl;
        created_at         |       id_str       | text | user.id  | user.location | coordinates.values[0] | coordinates.v
alues[1] 
---------------------------+--------------------+------+----------+---------------+-----------------------+--------------
---------
 MonSep3004:04:53+00002013 | 384529256681725952 |      | 31424214 | COLUMBUS      |                       |              
        
 MonSep3004:04:54+00002013 | 384529260872228864 |      | 67600981 | KryberWorld   |                     8 |              
      52
(2 rows)

六、向 HDFS 中写入数据

        PXF 只能向 HDFS 文件中写入数据,而对 Hive、HBase 和 JSON 等外部数据都是只读的。在使用 PXF 向 HDFS 文件写数据前,确认已经在集群所有节点上安装了 PXF HDFS 插件(Ambari 会自动安装),并授予了 HAWQ 用户(典型的是 gpadmin)对 HDFS 文件相应的读写权限。

1. 写 PXF 外部表

        PXF HDFS 插件支持两种可写的 profile:HdfsTextSimple 和 SequenceWritable。创建  HAWQ 可写外部表的语法如下:

CREATE WRITABLE EXTERNAL TABLE <table_name> 
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<host>[:<port>]/<path-to-hdfs-file>
    ?PROFILE=HdfsTextSimple|SequenceWritable[&<custom-option>=<value>[...]]')
FORMAT '[TEXT|CSV|CUSTOM]' (<formatting-properties>);

        CREATE EXTERNAL TABLE 语句中使用的各个关键字和相应值的描述如表9 所示。

关键字

<host>[:<port>]

HDFS NameNode 主机名、端口。

<path-to-hdfs-file>

HDFS 文件路径。

PROFILE

PROFILE 关键字指定为 HdfsTextSimple 或 SequenceWritable。

<custom-option>

与特定 PROFILE 对应的定制选项。

FORMAT 'TEXT'

当<path-to-hdfs-file>指向一个单行固定分隔符的平面文件时,使用该关键字。

FORMAT 'CSV'

当<path-to-hdfs-file>指向一个单行或多行的逗号分隔值(CSV)平面文件时,使用该关键字。

FORMAT 'CUSTOM'

SequenceWritable profile 使用该关键字。SequenceWritable 'CUSTOM'格式仅支持内建的formatter='pxfwritable_export(写)和formatter='pxfwritable_import(读)格式属性。

表9

2. 定制选项

        HdfsTextSimple 和 SequenceWritable profile 支持表10 所示的定制选项:

选项

值描述

Profile

COMPRESSION_CODEC

压缩编解码对应的 Java 类名。如果不提供,不会执行数据压缩。支持的压缩编解码包括:org.apache.hadoop.io.compress.DefaultCodec 和 org.apache.hadoop.io.compress.BZip2Codec

HdfsTextSimple、SequenceWritable

COMPRESSION_CODEC

org.apache.hadoop.io.compress.GzipCodec

HdfsTextSimple

COMPRESSION_TYPE

使用的压缩类型,支持的值为 RECORD(缺省)或 BLOCK。

HdfsTextSimple、SequenceWritable

DATA-SCHEMA

写入器的序列化/反序列化类名。类所在的 jar 文件必须在 PXF classpath 中,该选项被 SequenceWritable profile 使用,并且没有缺省值。

SequenceWritable

THREAD-SAFE

该 Boolean 值决定表查询是否运行在多线程模式,缺省值为 TRUE。

HdfsTextSimple、SequenceWritable

表10

3. 使用 HdfsTextSimple Profile 写数据

        HdfsTextSimple profile 用于向单行每记录(不含内嵌换行符)的固定分隔符平面文件写数据。使用 HdfsTextSimple Profile 的建立可写表时,可以选择记录或块压缩,支持以下压缩编解码方法。

  • org.apache.hadoop.io.compress.DefaultCodec
  • org.apache.hadoop.io.compress.GzipCodec
  • org.apache.hadoop.io.compress.BZip2Codec

        HdfsTextSimple profile 支持的格式属性为'delimiter',标识字段分隔符,缺省值为逗号(,)。

(1)创建可写外部表,数据写到 HDFS 的 /data/pxf_examples/pxfwritable_hdfs_textsimple1 目录中,字段分隔符为逗号。

create writable external table pxf_hdfs_writabletbl_1(location text, month text, num_orders int, total_sales float8)
            location ('pxf://hdp1:51200/data/pxf_examples/pxfwritable_hdfs_textsimple1?profile=hdfstextsimple')
          format 'text' (delimiter=e',');

(2)向 pxf_hdfs_writabletbl_1 表插入数据。

insert into pxf_hdfs_writabletbl_1 values ( 'Frankfurt', 'Mar', 777, 3956.98 );
insert into pxf_hdfs_writabletbl_1 values ( 'Cleveland', 'Oct', 3812, 96645.37 );
insert into pxf_hdfs_writabletbl_1 select * from pxf_hdfs_textsimple;

(3)查看 HDFS 文件的内容。

[hdfs@hdp1 ~]$ 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@hdp1 ~]$ hdfs dfs -ls /data/pxf_examples/pxfwritable_hdfs_textsimple1
Found 3 items
-rw-r--r--   3 pxf gpadmin         26 2017-03-22 10:45 /data/pxf_examples/pxfwritable_hdfs_textsimple1/236002_0
-rw-r--r--   3 pxf gpadmin         28 2017-03-22 10:45 /data/pxf_examples/pxfwritable_hdfs_textsimple1/236003_0
-rw-r--r--   3 pxf gpadmin         94 2017-03-22 10:46 /data/pxf_examples/pxfwritable_hdfs_textsimple1/236004_15
[hdfs@hdp1 ~]$ hdfs dfs -cat /data/pxf_examples/pxfwritable_hdfs_textsimple1/236002_0
Frankfurt,Mar,777,3956.98
[hdfs@hdp1 ~]$ hdfs dfs -cat /data/pxf_examples/pxfwritable_hdfs_textsimple1/236003_0
Cleveland,Oct,3812,96645.37
[hdfs@hdp1 ~]$ hdfs dfs -cat /data/pxf_examples/pxfwritable_hdfs_textsimple1/236004_15
Prague,Jan,101,4875.33
Rome,Mar,87,1557.39
Bangalore,May,317,8936.99
Beijing,Jul,411,11600.67
[hdfs@hdp1 ~]$

        可以看到,一共写入了 6 条记录,生成了 3 个文件。其中两个文件各有 1 条记录,另外一个文件中有 4 条记录,记录以逗号作为字段分隔符。

(4)查询可写外部表。

        HAWQ 不支持对可写外部表的查询,为了查询可写外部表的数据,需要建立一个可读外部表,指向 HDFS 的相应文件。

db1=# select * from pxf_hdfs_writabletbl_1;
ERROR:  External scan error: It is not possible to read from a WRITABLE external table. Create the table as READABLE instead. (CTranslatorDXLToPlStmt.cpp:1041)
db1=# create external table pxf_hdfs_textsimple_r1(location text, month text, num_orders int, total_sales float8)
db1-#             location ('pxf://hdp1:51200/data/pxf_examples/pxfwritable_hdfs_textsimple1?profile=hdfstextsimple')
db1-#             format 'csv';
CREATE EXTERNAL TABLE
db1=# select * from pxf_hdfs_textsimple_r1;
 location  | month | num_orders | total_sales 
-----------+-------+------------+-------------
 Cleveland | Oct   |       3812 |    96645.37
 Frankfurt | Mar   |        777 |     3956.98
 Prague    | Jan   |        101 |     4875.33
 Rome      | Mar   |         87 |     1557.39
 Bangalore | May   |        317 |     8936.99
 Beijing   | Jul   |        411 |    11600.67
(6 rows)

(5)建立一个使用 Gzip 压缩,并用冒号(:)做字段分隔符的可写外部表,注意类名区分大小写。

create writable external table pxf_hdfs_writabletbl_2 (location text, month text, num_orders int, total_sales float8) 
location ('pxf://hdp1:51200/data/pxf_examples/pxfwritable_hdfs_textsimple2?profile=hdfstextsimple&compression_codec=org.apache.hadoop.io.compress.GzipCodec') 
format 'text' (delimiter=e':');

(6)插入数据。

insert into pxf_hdfs_writabletbl_2 values ( 'Frankfurt', 'Mar', 777, 3956.98 );
insert into pxf_hdfs_writabletbl_2 values ( 'Cleveland', 'Oct', 3812, 96645.37 );

(7)使用 -text 参数查看压缩的数据。

[hdfs@hdp1 ~]$ hdfs dfs -text /data/pxf_examples/pxfwritable_hdfs_textsimple2/*
Frankfurt:Mar:777:3956.98
Cleveland:Oct:3812:96645.37
[hdfs@hdp1 ~]$

        可以看到刚插入的两条记录,记录以冒号作为字段分隔符。

七、删除外部表

        使用 drop external table <table_name> 语句删除外部表,该语句并不删除外部数据,因为外部数据不是由 HAWQ 管理的。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值