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

博客介绍了使用Spark-SQL满足基本的ES数据探查需求,利用elasticsearch-spark包扩展Spark Datasource,用sql查询es数据。还提及面临ES多索引关联sql查询时用spark-sql实现,指出原设计性能有问题,推荐先创建RDD减少数据量再操作,最后对DataSet生成进行了优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前针对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中添加依赖:

	<properties>
        <java.version>1.8</java.version>
        <scala.version>2.10.5</scala.version>
    </properties>

    <dependencies>
       
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.6.1</version>
        </dependency>

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.13.Final</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.10</artifactId>
            <version>2.1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>commons-compiler</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.10</artifactId>
            <version>2.1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>commons-compiler</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
       
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>${scala.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>commons-compiler</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.scala-lang.modules</groupId>
            <artifactId>scala-xml_2.11</artifactId>
            <version>1.0.6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>commons-compiler</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
  
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch-spark-20_2.10</artifactId>
            <version>6.3.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>janino</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.janino</groupId>
                    <artifactId>commons-compiler</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>commons-compiler</artifactId>
            <version>2.7.8</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
            <version>2.7.8</version>
        </dependency>
    </dependencies>

创建客户端

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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丧心病狂の程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值