http://www.cnblogs.com/wgp13x/p/4934521.html 內容一樣,樣式好的版本。
使用Hive或Impala執行SQL語句,對存儲在Elasticsearch中的數據操作
標簽: Hive Impala Elasticsearch Hadoop SQL Elasticsearch for Apache Hadoop
摘要:
使用Elasticsearch-SQL可以對存儲在Elasticsearch中的數據執行簡單的SQL查詢操作,然而並不支持多表join等聯接查詢。
Hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供簡單的SQL查詢功能,可以將SQL語句轉換為MapReduce任務進行運行。
因此如果Hive可以從Elasticsearch中取數據,並結合Hive的SQL查詢功能,便能做到較為復雜的SQL查詢操作。
我們的目標是:
- 支持Elasticsearch多表聯接查詢;
- 結合Elasticsearch搜索引擎提高SQL查詢效率。
基礎環境
CentOS-6.5
hive:hive-0.13.1+cdh5.3.6+397
impala:impala-2.1.5+cdh5.3.6+0
spark:spark-1.2.0+cdh5.3.6+379
elasticsearch:elasticsearch-1.7.1
elasticsearch-hadoop-hive:elasticsearch-hadoop-hive-2.1.1
Elasticsearch簡介
Elasticsearch是一個基於Apache Lucene(TM)的開源搜索引擎。它基於RESTful web接口,提供實時、穩定、可靠的分布式服務。
Elasticsearch的數據類型
ES使用JSON作為數據交互格式,所以簡單來說,JSON支持的數據類型,ES都支持。
String: string
Whole number: byte, short, integer, long
Floating point: float, double
Boolean: boolean
Date: date
除了以上Core Types(核心數據類型),還有:Array Type、Object Type、Root Object Type、Nested Type、IP Type、Geo-point Type、Geo Shap Type、Attachment Type等。
Solr的數據類型
相應的Solr的數據類型有:
| BCDIntField | BCDLongField | BCDStrField | BinaryField | BoolField |
| -------- | ----- | ---- |
|二進制整形字段|二進制長整形字段|二進制字符型字段|二進制數據| 包含true或者false,值的第一個字符如果是1、t、T均表示true,其他為false
|ByteField|DateField|DoubleField|ExternalFileField|FloatField
|一個字節數據|一個精確到毫秒的時間值|
|IntField|Location|LongField|Point|RandomSortField|
| |方位搜索用到,存經緯度值||N維點搜索,在藍圖或者CAD圖中使用|不包含值,當查詢時按這種類型的字段排序時會產生隨機排序。使用該特性時需要是一個動態字段|
|ShortField|StrField|TextField|UUIDField
||UTF-8編碼的字符串或Unicode|文本類型,一般包含多個單詞或漢字|唯一識別碼,單傳入的值是“NEW”時,Solr將為其創建1個UUID值
數據存儲在Elasticsearch上,使用Hive執行SQL語句
要打通Elasticsearch與Hive,需要Elasticsearch for Apache Hadoop下的elasticsearch-hadoop-hive。
Elasticsearch for Apache Hadoop提供了三類解決方案:Elasticsearch on YARN、repository-hdfs、elasticsearch-hadoop proper。
詳情查看:Elasticsearch for Apache Hadoop。
創建Hive外部表
先有Hive再有Elasticsearch
在Elasticsearch中並無表,甚至並無Elasticsearch服務時,可以通過執行以下語句在Hive中創建一個新的外部表。
#在Hive中創建一個新的外部表
hive> CREATE EXTERNAL TABLE hive_es_angel(
id BIGINT,
name STRING)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.nodes'='192.168.181.190','es.resource' = 'indexname/typename');
這里指定了ES的地址與索引名和類型名(index-type)。通過執行此語句,便可以在Hive查看到結構正確的表。
注意:
elasticsearch-hadoop will always convert Hive column names to lower-case,就是說建立起的Hive表中所有字段均變為小寫。
在執行此語句后,並不會在ElasticSearch中建立指定的索引與類型,只有當后續在Hive中執行SQL插入語句時,才會在ElasticSearch中建立指定的索引與類型,並插入相關數據。
執行此語句並不會拋出錯誤,這與HBase和Hive建立關聯時的情況不一樣,創建HBase外部表時需要查看HBase中信息。 更多細節可以查看《使用Hive或Impala執行SQL語句,對存儲在HBase中的數據操作》一文。
先有Elasticsearch再有Hive
在ElasticSearch中已有索引和類型,甚至在其中存儲有數據時,我們可以在Hive中直接對ElasticSearch中數據進行操作。
即是在Hive中執行以上創建ES外部表的命令,即可以在Hue中看到ElasticSearch中的數據。
以下是幾種典型的創建Hive外部表命令:
- 在Hive指定decimal數據類型
CREATE EXTERNAL TABLE hive_es_decimal(
price DECIMAL(12,2) )
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.nodes'='192.168.181.160','es.resource' = 'indexname/typename');
默認情況下,是以列名稱與ES映射的,注意:elasticsearch-hadoop will always convert Hive column names to lower-case,此時ES列名也必須小寫,否則映射不上。
經驗證,以上語句有問題。如Hive定義為Decimal,而ES只能Double,會出現org.apache.hadoop.hive.serde2.io.DoubleWritable cannot be cast to org.apache.hadoop.hive.serde2.io.HiveDecimalWritable
錯誤。
- 指定列映射關系
CREATE EXTERNAL TABLE hive_es_map(
price DOUBLE,
itemid BIGINT,
myname STRING
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES('es.nodes'='192.168.181.160','es.resource' = 'indexname/typename','es.mapping.names' = 'itemid:itemId, myname:myName, devicenumber:deviceNumber');
在創建Hive外部表時指定映射關系時,也需要對應好數據類型,否則也會出現類似數據類型轉換失敗錯誤。
注意:
從ES的date數據類型轉換到Hive的date/timestamp數據類型,均出錯,出錯信息為:java.io.IOException: java.lang.IllegalArgumentException: 2015-06-03T14:54:46+0800
向Elasticsearch寫
hive> add jar /opt/cloudera/parcels/CDH-5.3.6-1.cdh5.3.6.p0.11/lib/hive/lib/elasticsearch-hadoop-hive-2.1.1.jar;
#向ES中導入Hive中表sample_07數據
hive> INSERT OVERWRITE TABLE hive_es_test
SELECT s.id, s.code
FROM sample_07 s;
當Elasticsearch中不存在相應索引時,經過執行以上插入語句,在Elasticsearch中就會創建一個新索引:indexname,新類型:typename(當然是在Hive創建新外部表時指定好的),數據也已經添加入其中。
沒有指定列映射類型時,下面是部分默認情況下的Hive與ElasticSearch數據類型映射關系。
Hive | ES | 默認映射結果 |
---|---|---|
bigint | long | 無問題 |
timestamp | date | 無問題 |
double | double | 無問題 |
date | string | 有問題 |
decimal | string | 有問題 |
注意:
可以看到有問題的映射是兩端不能匹配的映射。當存在有問題的映射時,在Hive中執行SELECT * FROM table_decimal
時會拋出異常:
Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassCastException: org.apache.hadoop.io.Text cannot be cast to org.apache.hadoop.hive.serde2.io.HiveDecimalWritable
即數據類型從ElasticSearch到Hive數據類型轉換失敗。可見,在使用Hive對存儲在ElasticSearch中的數據進行操作時,要注意使用雙方均支持的數據類型。
從Elasticsearch讀
我們選擇以下幾條有代表性的SQL查詢語句,來驗證使用Hive可以對存儲在Elasticsearch中的數據進行正確的查詢操作。
where子句
hive> add jar /opt/cloudera/parcels/CDH-5.3.6-1.cdh5.3.6.p0.11/lib/hive/lib/elasticsearch-hadoop-hive-2.1.1.jar;
hive> select count(*) from hive_es_angel where id>1000;
在執行此語句時,可以看到map-reduce的執行過程:
Hadoop job information for Stage-1: number of mappers: 5; number of reducers: 1
2015-10-15 14:30:28,181 Stage-1 map = 0%, reduce = 0%
2015-10-15 14:30:38,623 Stage-1 map = 2%, reduce = 0%, Cumulative CPU 4.07 sec
2015-10-15 14:30:39,678 Stage-1 map = 4%, reduce = 0%, Cumulative CPU 8.8 sec
2015-10-15 14:30:41,766 Stage-1 map = 5%, reduce = 0%, Cumulative CPU 9.36 sec
這說明,Hive在執行此語句時,並沒有用到Elasticsearch建立的索引,以使查詢效率更高,而是將Elasticsearch相應數據全部獲取下來。
注意:
Hive並沒有用到Elasticsearch查詢高效的好處。
普通表與外表關聯
hive> add jar /opt/cloudera/parcels/CDH-5.3.6-1.cdh5.3.6.p0.11/lib/hive/lib/elasticsearch-hadoop-hive-2.1.1.jar;
hive> select * from hive_es_angel left join sample_08 on hive_es_angel.name=sample_08.code;
其中sample_08表是Hive普通表,hive_es_angel是數據存儲在HBase中的Hive外表。
經驗證,通過執行上面語句,可以將Hive普通表與Hive的Elasticsearch外表進行正確的關聯。
這樣一來,ES的SQL插件elasticsearch-sql所不能完成的join等查詢語句,便可以通過Hive很好的執行了。
Double數據類型求和
hive> add jar /opt/cloudera/parcels/CDH-5.3.6-1.cdh5.3.6.p0.11/lib/hive/lib/elasticsearch-hadoop-hive-2.1.1.jar;
hive> SELECT SUM(field_double) FROM hive_es_double;
由於ElasticSearch並不支持decimal數據類型,故只能在Hive中對小數列創建double數據類型,這時使用Hive也無法進行精確求和,這在需要進行小數精確統計時,是一大問題。
Solr也有此缺陷,可見目前ES、Solr天生不適合進行精確計算。故將數據放在ES中,使用Hive或Impala進行SQL精確統計,並非一個好辦法。
數據存儲在Elasticsearch上,使用Impala執行SQL語句
hive中建立的普通表,impala可以讀取使用。執行join語句時,impala明顯比hive快很多。在impala中執行INVALIDATE METADATA 、 REFRESH table_name語句以便 Impala 識別新的或已更改的數據。
但是,對於EXTERNAL TABLE數據存放在ES上的,Hive SQL可以正確執行,Impala SQL執行不正確,出錯信息如下所示。
ERROR: AnalysisException: Failed to load metadata for table: default.hive_table
CAUSED BY: TableLoadingException: Unrecognized table type for table: default. es_table
可見使用elasticsearch-hadoop來做Impala計算,是不可行的。相比較下,數據存儲在HBase中,使用Impala執行SQL語句卻沒有問題。具體可以查看《使用Hive或Impala執行SQL語句,對存儲在HBase中的數據操作》一文。
綜上所述
數據存儲在Elasticsearch中,使用Hive進行SQL操作,並不是一個好主意,這是由於ES的數據類型所限導致的ES與Hive的數據類型對應問題,並且Hive並不能用到Elasticsearch建立的索引的高效查詢好處。雖然以上方案可以解決使用Hive對Elasticsearch較復雜SQL語句查詢,但不方便也不高效,且Impala也不能支持。
故,目標1達成,但目標2沒有達成。
博客園既不支持目錄,也不支持表格,真是不舒服。我在考慮要不要換個地方發表。
嫌樣式不好的,大家看這篇吧:http://www.cnblogs.com/wgp13x/p/4934521.html內容一樣,樣式稍好看些。
信息系統集成項目管理人員資質證書還有公司需要的啊?掛靠私聊。