本文主要為您介紹如何使用Hive或者HadoopMR訪問表格存儲中的表。
數據準備
在表格存儲中準備一張數據表pet,name是唯一的一列主鍵,數據示例請參見下表。
表中空白部分無需寫入,因為表格存儲是schema-free的存儲結構,沒有值也無需寫入NULL。
name | owner | species | sex | birth | death |
Fluffy | Harold | cat | f | 1993-02-04 | |
Claws | Gwen | cat | m | 1994-03-17 | |
Buffy | Harold | dog | f | 1989-05-13 | |
Fang | Benny | dog | m | 1990-08-27 | |
Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
Chirpy | Gwen | bird | f | 1998-09-11 | |
Whistler | Gwen | bird | 1997-12-09 | ||
Slim | Benny | snake | m | 1996-04-29 | |
Puffball | Diane | hamster | f | 1999-03-30 |
前提條件
已準備好Hadoop、Hive、JDK環境以及表格存儲Java SDK和EMR SDK依賴包。更多信息,請參見準備工作。
Hive訪問示例
HADOOP_HOME及HADOOP_CLASSPATH可以添加到/etc/profile中,示例如下:
export HADOOP_HOME=${您的Hadoop安裝目錄} export HADOOP_CLASSPATH=emr-tablestore-1.4.2.jar:tablestore-4.3.1-jar-with-dependencies.jar:joda-time-2.9.4.jar
執行
bin/hive
命令進入Hive后,創建外表。示例如下:CREATE EXTERNAL TABLE pet (name STRING, owner STRING, species STRING, sex STRING, birth STRING, death STRING) STORED BY 'com.aliyun.openservices.tablestore.hive.TableStoreStorageHandler' WITH SERDEPROPERTIES( "tablestore.columns.mapping"="name,owner,species,sex,birth,death") TBLPROPERTIES ( "tablestore.endpoint"="YourEndpoint", "tablestore.access_key_id"="YourAccessKeyId", "tablestore.access_key_secret"="YourAccessKeySecret", "tablestore.table.name"="pet");
具體配置項說明請參見下表。
配置項
說明
WITH SERDEPROPERTIES
字段映射配置,包括tablestore.columns.mapping選項配置。
在默認情況下,外表的字段名即為表格存儲上表的列名(主鍵列名或屬性列名)。但有時外表的字段名和表上列名并不一致(例如處理大小寫或字符集相關的問題),此時需要指定tablestore.columns.mapping。該參數為一個英文逗號分隔的字符串,每個分隔之間不能添加空格,每一項都是表中列名,順序與外表字段保持一致。
說明表格存儲的列名支持空白字符,所以空白也會被認為是表中列名的一部分。
TBLPROPERTIES
表的屬性配置。包括如下選項:
tablestore.endpoint(必選):訪問表格存儲的服務地址,您可以在表格存儲控制臺上查看實例的Endpoint信息。關于服務地址的更多信息,請參見服務地址。
tablestore.instance(可選):表格存儲的實例名稱。如果不填寫,則為tablestore.endpoint的第一段。關于實例的更多信息,請參見實例。
tablestore.access_key_id(必選):阿里云賬號或者RAM用戶的AccessKey ID。更多信息,請參見獲取AccessKey。
當要使用STS服務臨時訪問資源時,請設置此參數為臨時訪問憑證的AccessKey ID。
tablestore.access_key_secret(必選):阿里云賬號或者RAM用戶的AccessKey Secret。更多信息,請參見獲取AccessKey。
當要使用STS服務臨時訪問資源時,請設置此參數為臨時訪問憑證的AccessKey Secret。
tablestore.sts_token(可選):臨時訪問憑證的安全令牌。當要使用STS服務臨時訪問資源時,才需要設置此參數。更多信息,請參見通過RAM Policy為RAM用戶授權。
tablestore.table.name(必選):表格存儲中對應的表名。
查詢表中數據。
執行
SELECT * FROM pet;
命令查詢表中所有行數據。返回結果示例如下:
Bowser Diane dog m 1979-08-31 1995-07-29 Buffy Harold dog f 1989-05-13 NULL Chirpy Gwen bird f 1998-09-11 NULL Claws Gwen cat m 1994-03-17 NULL Fang Benny dog m 1990-08-27 NULL Fluffy Harold cat f 1993-02-04 NULL Puffball Diane hamster f 1999-03-30 NULL Slim Benny snake m 1996-04-29 NULL Whistler Gwen bird NULL 1997-12-09 NULL Time taken: 5.045 seconds, Fetched 9 row(s)
執行
SELECT * FROM pet WHERE birth > "1995-01-01";
命令查詢表中birth列值大于1995-01-01的行數據。返回結果示例如下:
Chirpy Gwen bird f 1998-09-11 NULL Puffball Diane hamster f 1999-03-30 NULL Slim Benny snake m 1996-04-29 NULL Whistler Gwen bird NULL 1997-12-09 NULL Time taken: 1.41 seconds, Fetched 4 row(s)
HadoopMR訪問示例
以下示例介紹如何使用HadoopMR程序統計數據表pet的行數。
構建Mappers和Reducers
public class RowCounter { public static class RowCounterMapper extends Mapper<PrimaryKeyWritable, RowWritable, Text, LongWritable> { private final static Text agg = new Text("TOTAL"); private final static LongWritable one = new LongWritable(1); @Override public void map( PrimaryKeyWritable key, RowWritable value, Context context) throws IOException, InterruptedException { context.write(agg, one); } } public static class IntSumReducer extends Reducer<Text,LongWritable,Text,LongWritable> { @Override public void reduce( Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { long sum = 0; for (LongWritable val : values) { sum += val.get(); } context.write(key, new LongWritable(sum)); } } }
數據源每從表格存儲上讀出一行,都會調用一次mapper的map()。PrimaryKeyWritable和RowWritable兩個參數分別對應這行的主鍵以及該行的內容。您可以通過調用PrimaryKeyWritable.getPrimaryKey()和RowWritable.getRow()取得表格存儲Java SDK定義的主鍵對象及行對象。
配置表格存儲作為mapper的數據源。
private static RangeRowQueryCriteria fetchCriteria() { RangeRowQueryCriteria res = new RangeRowQueryCriteria("YourTableName"); res.setMaxVersions(1); List<PrimaryKeyColumn> lower = new ArrayList<PrimaryKeyColumn>(); List<PrimaryKeyColumn> upper = new ArrayList<PrimaryKeyColumn>(); lower.add(new PrimaryKeyColumn("YourPkeyName", PrimaryKeyValue.INF_MIN)); upper.add(new PrimaryKeyColumn("YourPkeyName", PrimaryKeyValue.INF_MAX)); res.setInclusiveStartPrimaryKey(new PrimaryKey(lower)); res.setExclusiveEndPrimaryKey(new PrimaryKey(upper)); return res; } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "row count"); job.addFileToClassPath(new Path("hadoop-connector.jar")); job.setJarByClass(RowCounter.class); job.setMapperClass(RowCounterMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(LongWritable.class); job.setInputFormatClass(TableStoreInputFormat.class); TableStoreInputFormat.setEndpoint(job, "https://YourInstance.Region.ots.aliyuncs.com/"); TableStoreInputFormat.setCredential(job, "YourAccessKeyId", "YourAccessKeySecret"); TableStoreInputFormat.addCriteria(job, fetchCriteria()); FileOutputFormat.setOutputPath(job, new Path("output")); System.exit(job.waitForCompletion(true) ? 0 : 1); }
示例中使用job.setInputFormatClass(TableStoreInputFormat.class)將表格存儲設置為數據源,除此之外,還需要:
把hadoop-connector.jar部署到集群上并添加到classpath中。路徑為addFileToClassPath()指定hadoop-connector.jar的本地路徑。代碼中假定hadoop-connector.jar在當前路徑。
訪問表格存儲需要指定入口和身份。通過TableStoreInputFormat.setEndpoint()和TableStoreInputFormat.setCredential()設置訪問表格存儲需要指定的Endpoint和AccessKey信息。
指定一張表用來計數。
說明每調用一次addCriteria()可以在數據源里添加一個Java SDK定義的RangeRowQueryCriteria對象。可以多次調用addCriteria()。RangeRowQueryCriteria對象與表格存儲Java SDK GetRange接口所用的RangeRowQueryCriteria對象具有相同的限制條件。
使用RangeRowQueryCriteria的setFilter()和addColumnsToGet()可以在表格存儲的服務器端過濾掉不必要的行和列,減少訪問數據的大小,降低成本,提高性能。
通過添加對應多張表的多個RangeRowQueryCriteria,可以實現多表的union。
通過添加同一張表的多個RangeRowQueryCriteria,可以做到更均勻的切分。TableStore-Hadoop Connector會根據一些策略將用戶傳入的范圍切細。
程序運行示例
設置HADOOP_CLASSPATH。
HADOOP_CLASSPATH=hadoop-connector.jar bin/hadoop jar row-counter.jar
執行
find output -type f
命令查找output目錄下的所有文件。返回結果示例如下:
output/_SUCCESS output/part-r-00000 output/._SUCCESS.crc output/.part-r-00000.crc
執行
cat output/part-r-00000
命令統計運行結果中的行數。TOTAL 9
類型轉換說明
表格存儲支持的數據類型與Hive或者Spark支持的數據類型不完全相同。
下表列出了從表格存儲的數據類型(行)轉換到Hive或Spark數據類型(列)的支持情況。
類型轉換 | TINYINT | SMALLINT | INT | BIGINT | FLOAT | DOUBLE | BOOLEAN | STRING | BINARY |
INTEGER | 支持,損失精度 | 支持,損失精度 | 支持,損失精度 | 支持 | 支持,損失精度 | 支持,損失精度 | 不支持 | 不支持 | 不支持 |
DOUBLE | 支持,損失精度 | 支持,損失精度 | 支持,損失精度 | 支持,損失精度 | 支持,損失精度 | 支持 | 不支持 | 不支持 | 不支持 |
BOOLEAN | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 支持 | 不支持 | 不支持 |
STRING | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 支持 | 不支持 |
BINARY | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 支持 |