

# 在 Hive 中创建外部表
<a name="EMRforDynamoDB.ExternalTableForDDB"></a>

在 [教程：使用 Amazon DynamoDB 和 Apache Hive](EMRforDynamoDB.Tutorial.md) 中，您创建了映射到 DynamoDB 表的外部 Hive 表。对外部表发出 HiveQL 语句时，读取和写入操作将传递到 DynamoDB 表。

可以将外部表视为指向在其他位置管理和存储的数据源的指针。在这种情况下，基础数据源是 DynamoDB 表。（表必须已经存在。无法从 Hive 创建、更新或删除 DynamoDB 表。） 可以使用 `CREATE EXTERNAL TABLE` 语句创建外部表。之后，可以使用 HiveQL 处理 DynamoDB 的数据，就好像这些数据在 Hive 中本地存储一样。

**注意**  
可以使用 `INSERT` 语句将数据插入到外部表，使用 `SELECT` 语句从中选择数据。但无法使用 `UPDATE` 或 `DELETE` 语句处理表中的数据。

如果不再需要外部表，可以使用 `DROP TABLE` 语句移除。在这种情况下，`DROP TABLE` 仅移除 Hive 中的外部表，不影响底层 DynamoDB 表或其任何数据。

**Topics**
+ [CREATE EXTERNAL TABLE 语法](#EMRforDynamoDB.ExternalTableForDDB.Syntax)
+ [数据类型映射](#EMRforDynamoDB.ExternalTableForDDB.DataTypes)

## CREATE EXTERNAL TABLE 语法
<a name="EMRforDynamoDB.ExternalTableForDDB.Syntax"></a>

下面显示用于创建映射到 DynamoDB 表的外部 Hive 表的 HiveQL 语法：

```
CREATE EXTERNAL TABLE hive_table
    (hive_column1_name hive_column1_datatype, hive_column2_name hive_column2_datatype...)
STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'
TBLPROPERTIES (
    "dynamodb.table.name" = "dynamodb_table",
    "dynamodb.column.mapping" = "hive_column1_name:dynamodb_attribute1_name,hive_column2_name:dynamodb_attribute2_name..."
);
```

第 1 行是 `CREATE EXTERNAL TABLE` 语句开始，在此提供要创建的 Hive 表的名称 (*hive\$1table*)。

第 2 行指定 *hive\$1table* 的列和数据类型。需要定义与 DynamoDB 表属性对应的列和数据类型。

第 3 行是 `STORED BY` 子句，在此指定处理 Hive 和 DynamoDB 表之间数据管理的类。对于 DynamoDB，`STORED BY` 应设置为 `'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler'`。

第 4 行是 `TBLPROPERTIES` 子句开始，在此定义以下 `DynamoDBStorageHandler` 参数：
+ `dynamodb.table.name`—DynamoDB 表的名称。
+  `dynamodb.column.mapping`—Hive 表的列名与 DynamoDB 表相应属性对。每对采用 *hive\$1column\$1name:dynamodb\$1attribute\$1name* 形式，由逗号分隔。

请注意以下几点：
+ Hive 表名称不必与 DynamoDB 表名称相同。
+ Hive 表列名称不必与 DynamoDB 表中的名称相同。
+ `dynamodb.table.name` 指定的表必须存在于 DynamoDB 中。
+ 对于：`dynamodb.column.mapping`
  + 必须映射 DynamoDB 表的键架构属性。这包括分区键和排序键（如果有）。
  + 不必映射 DynamoDB 表的非键属性。但是查询 Hive 表时，看不到这些属性的任何数据。
  + 如果 Hive 表列和 DynamoDB 属性的数据类型不兼容，查询 Hive 表时将在这些列中看到 `NULL`。

**注意**  
`CREATE EXTERNAL TABLE` 语句不会对 `TBLPROPERTIES` 子句执行任何验证。访问表时，为 `dynamodb.table.name` 和 `dynamodb.column.mapping` 提供的值仅由 `DynamoDBStorageHandler` 类验证。

## 数据类型映射
<a name="EMRforDynamoDB.ExternalTableForDDB.DataTypes"></a>

下表显示 DynamoDB 数据类型和兼容的 Hive 数据类型：


****  

| DynamoDB 数据类型 | Hive 数据类型 | 
| --- | --- | 
|  String  |  `STRING`  | 
|  Number  |  `BIGINT` 或 `DOUBLE`  | 
|  Binary  |  `BINARY`  | 
|  String Set  |  `ARRAY<STRING>`  | 
|  Number Set  |  `ARRAY<BIGINT>` 或 `ARRAY<DOUBLE>`  | 
|  Binary Set  |  `ARRAY<BINARY>`  | 

**注意**  
`DynamoDBStorageHandler` 类不支持以下 DynamoDB 数据类型，无法用于 `dynamodb.column.mapping`：  
Map
列表
布尔值
Null
但是，如果您需要使用这些数据类型，则可以创建一个名为 `item` 的单个实体，该实体将整个 DynamoDB 项目表示为映射中键和值的字符串映射。有关更多信息，请参阅 [复制没有列映射的数据](EMRforDynamoDB.CopyingData.S3.md#EMRforDynamoDB.CopyingData.S3.NoColumnMapping)。

如果要映射 Number 类型的 DynamoDB 属性，则必须选择合适 Hive 类型：
+ Hive `BIGINT` 类型用于 8 字节有符号整数。和 Java 的 `long` 数据类型相同。
+ Hive `DOUBLE` 类型用于 8 位双精度浮点数。和 Java 的 `double` 类型相同。

如果 DynamoDB 中存储的数字数据精度高于选择的 Hive 数据类型，则访问 DynamoDB 数据可能会导致精度损失。

如果将 Binary 类型数据从 DynamoDB 导出到 (Amazon S3) 或 HDFS，则数据以 Base64 编码的字符串形式存储。如果将数据从 Amazon S3 或 HDFS 导入到 DynamoDB Binary 类型，则必须确保数据编码为 Base64 字符串。