目前针对SQL on ElasticSearch
已经有了比较好的解决方案:elasticsearch-sql,其实Spark-SQL也可以满足一些基本的ES数据探查的需求,实现起来也相对简单。
elasticsearch-spark的包针对ES扩展了Spark
Datasource,我们可以使用sql查询es中的数据,中间Spark充当了“SQL解析器”的角色。作者:PowerMe 链接:https://www.jianshu.com/p/6b5230fde602 来源:简书
但是很多时候我们还不得不面临一些对elasticsearch中的多个索引的关联sql查询需求,这时候就只能使用spark-sql来实现。
pom.xml中添加依赖:
1.8
2.10.5
org.elasticsearch.client
elasticsearch-rest-high-level-client
6.6.1
org.elasticsearch.client
elasticsearch-rest-client
6.6.1
io.netty
netty-all
4.1.13.Final
org.apache.httpcomponents
httpclient
4.5.2
javax.servlet
servlet-api
org.apache.spark
spark-core_2.10
2.1.2
org.codehaus.janino
janino
org.codehaus.janino
commons-compiler
org.apache.spark
spark-sql_2.10
2.1.2
org.codehaus.janino
janino
org.codehaus.janino
commons-compiler
org.scala-lang
scala-library
${scala.version}
org.codehaus.janino
janino
org.codehaus.janino
commons-compiler
org.scala-lang.modules
scala-xml_2.11
1.0.6
org.codehaus.janino
janino
org.codehaus.janino
commons-compiler
org.elasticsearch
elasticsearch-spark-20_2.10
6.3.2
org.codehaus.janino
janino
org.codehaus.janino
commons-compiler
org.codehaus.janino
commons-compiler
2.7.8
org.codehaus.janino
janino
2.7.8
es rest客户端:
restClient = RestClient.builder(
new HttpHost("cdh01", 9200, "http"),
new HttpHost("cdh02", 9200, "http"),
new HttpHost("cdh03", 9200, "http"),
new HttpHost("cdh04", 9200, "http"),
new HttpHost("cdh05", 9200, "http")).build();
java spark context:
SparkConf sparkConf = new SparkConf().setAppName("HBaseTest").setMaster("local[*]");
sparkConf.set("es.index.auto.create","true"); //在spark中自动创建es中的索引
sparkConf.set("es.nodes","192.168.1.1");//设置在spark中连接es的url和端口
sparkConf.set("es.port","9200");
sparkConf.set("es.nodes.wan.only","true");
sc = new JavaSparkContext(sparkConf);
下面是在我们系统中使用的部分关键代码的简化版本。
"table_array"是外部传入的一个索引名的链表,"v"是我们在es中创建的type。
// spark
SQLContext sql = new SQLContext(sc);
// 注册临时表
for (int i = 0; i < tableArray.size(); i++){
sql.read().format("es").load(table_Array.get(i) + "/v").registerTempTable(table_Array.get(i));
}
// 执行sql
Dataset df = sql.sql(sqlString);
这种设计方法虽然做到了功能的demo实现,但是在性能上存在严重的问题,由于sql.read()进行了全表导入,会占用大量的内存和计算时间。
比较推荐的还是SparkSql 读取elasticsearch 表数据,先通过query条件创建RDD以减少读入数据量,然后在RDD的基础上进行合并sql操作。
使用RDD的方法虽然解决了加载数据量过多的问题,但是也使我们的接口失去了通用性,所以最后我们使用了elasticsearch on hadoop接口可以使用 string url query 的特性,对DataSet的生成进行了优化。
Dataset d = JavaEsSparkSQL.esDF(sql, tableNameSpace + tableName, query);
d.registerTempTable(tableNameSpace + tableName);