通过 spark sql 支持 elasticsearch 的多表(两表或以上) sql 关联查询

目前针对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);

动态导入数据及sql执行

下面是在我们系统中使用的部分关键代码的简化版本。
"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);

你可能感兴趣的:(database,spark,elasticsearch)