`
weitao1026
  • 浏览: 1054213 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Elasticsearch 当数据库使:Join

 
阅读更多

把 Elasticsearch 当数据库使 系列:

 

推销Elasticsearch

时间序列数据库的秘密(1)—— 介绍
时间序列数据库的秘密(2)——索引
时间序列数据库的秘密(3)——加载和分布式计算

用SQL查询Elasticsearch

https://github.com/taowen/es-monitor

【01】把 Elasticsearch 当数据库使:表结构定义
【02】把 Elasticsearch 当数据库使:过滤和排序
【03】把 Elasticsearch 当数据库使:简单指标
【04】把 Elasticsearch 当数据库使:按字段聚合
【05】把 Elasticsearch 当数据库使:HISTOGRAM聚合
【06】把 Elasticsearch 当数据库使:CASE WHEN 聚合
【07】把 Elasticsearch 当数据库使:聚合后排序
【08】把 Elasticsearch 当数据库使:计算后再聚合
【09】把 Elasticsearch 当数据库使:HAVING与Pipeline Aggregation
【10】把 Elasticsearch 当数据库使:Drill Down 下钻
【11】把 Elasticsearch 当数据库使:Filter 下钻
【12】把 Elasticsearch 当数据库使:聚合后再计算
【13】把 Elasticsearch 当数据库使:Join

 

 

 

 

使用 https://github.com/taowen/es-monitor 可以用 SQL 进行 elasticsearch 的查询。要真正把Elasticsearch当作数据库来使,Join是一个绕不过的话题。关于Elasticsearch如何支持join,这个slide总结得很好:http://www.slideshare.net/sirensolutions/searching-relational-data-with-elasticsearch。总体来说有这么几种方式:

  • 完全不join,把关联表的字段融合到一张表里。当然这会造成数据的冗余

  • 录入的时候join:使用 nested documents(nested document和主文档是同segment存储的,对于一个symbol,几千万个quote这样的场景就不适合了)

  • 录入的时候join:使用 siren

  • 查询时join:使用 parent/child (这个是elasticsearch的特性,要求parent/child同shard存在)

  • 查询时join:使用 siren-joins(就是一个在服务端求值的filter,然后把结果发布给每个shard去做二次match)

  • 查询时join:在客户端拼装第二个查询(和siren-joins差不多,但是多了一次客户端到服务器的来回)

  • 查询时join:在coordinate节点上做两个查询的join合并(https://github.com/NLPchina/elasticsearch-sql

我个人喜欢的是siren-joins和客户端拼装这两种方案。这两种方案都是先做了一次查询,把查询结果再次分发到每个分布式节点上再次去做分布式的聚合。相比在coordinate节点上去做join合并更scalable。

客户端求值

首先我来看如何在客户端完成结果集的求值

$ cat << EOF | python2.6 es_query.py http://127.0.0.1:9200
    SELECT symbol FROM symbol WHERE sector='Finance' LIMIT 1000;
    SAVE RESULT AS finance_symbols;
EOF

这里引入的 SAVE RESULT AS 就是用于触发前面的SQL的求值,并把结果集命名为 finance_symbols。如果因为一些中间结果我们不需要,我们也可以用REMOVE 命令把求值结果删除

$ cat << EOF | python2.6 es_query.py http://127.0.0.1:9200
    SELECT symbol FROM symbol WHERE sector='Finance' LIMIT 1000;
    SAVE RESULT AS finance_symbols;
    REMOVE RESULT finance_symbols;
EOF

甚至我们可以使用任意的python代码来修改result_map。

$ cat << EOF | python2.6 es_query.py http://127.0.0.1:9200
    SELECT symbol FROM symbol WHERE sector='Finance' LIMIT 1000;
    SAVE RESULT AS finance_symbols;
    result_map['finance_symbols'] = result_map['finance_symbols'][1:-1];
EOF

客户端Join

在客户端求值的基础上,我们可以利用客户端保留的结果集来发第二个请求。

cat << EOF | python2.6 es_query.py http://127.0.0.1:9200
    SELECT symbol FROM symbol WHERE sector='Finance' LIMIT 5;
    SAVE RESULT AS finance_symbols;
    SELECT MAX(adj_close) FROM quote 
        JOIN finance_symbols ON quote.symbol = finance_symbols.symbol;
    REMOVE RESULT finance_symbols;
EOF

这个产生的Elaticsearch请求是这样的两条:

{
  "query": {
    "term": {
      "sector": "Finance"
    }
  }, 
  "size": 5
}

然后根据其返回,产生了第二个请求

{
  "query": {
    "bool": {
      "filter": [
        {}, 
        {
          "terms": {
            "symbol": [
              "TFSC", 
              "TFSCR", 
              "TFSCU", 
              "TFSCW", 
              "PIH"
            ]
          }
        }
      ]
    }
  }, 
  "aggs": {
    "MAX(adj_close)": {
      "max": {
        "field": "adj_close"
      }
    }
  }, 
  "size": 0
}

可以看到,所谓客户端join,就是用前一次的查询结果拼出了第二次查询的条件(terms filter)。

服务端Join

有了 siren-join 插件(https://github.com/sirensolutions/siren-join),我们可以在服务端完成同样的join操作

cat << EOF | python2.6 es_query.py http://127.0.0.1:9200
    WITH finance_symbols AS (SELECT symbol FROM symbol WHERE sector='Finance' LIMIT 5);
    SELECT MAX(adj_close) FROM quote 
        JOIN finance_symbols ON quote.symbol = finance_symbols.symbol;
EOF

前面第一个查询是用SAVE RESULT AS求值并命名为finance_symbols,这里我们并没有求值而是给其取了一个名字(WITH AS),然后就可以引用了。

{
  "query": {
    "bool": {
      "filter": [
        {}, 
        {
          "filterjoin": {
            "symbol": {
              "indices": "symbol*", 
              "path": "symbol", 
              "query": {
                "term": {
                  "sector": "Finance"
                }
              }
            }
          }
        }
      ]
    }
  }, 
  "aggs": {
    "MAX(adj_close)": {
      "max": {
        "field": "adj_close"
      }
    }
  }, 
  "size": 0
}

可见产生的filterjoin把两步合为一步了。注意对于filterjoin查询,需要POST _coordinate_search 而不是_search这个URL。
Profile

[
  {
    "query": [
      {
        "query_type": "BoostQuery",
        "lucene": "ConstantScore(BytesFieldDataTermsQuery::[size=8272])^0.0",
        "time": "29.32334300ms",
        "breakdown": {
          "score": 0,
          "create_weight": 360426,
          "next_doc": 137906,
          "match": 0,
          "build_scorer": 15027540,
          "advance": 0
        },
        "children": [
          {
            "query_type": "BytesFieldDataTermsQuery",
            "lucene": "BytesFieldDataTermsQuery::[size=8272]",
            "time": "13.79747100ms",
            "breakdown": {
              "score": 0,
              "create_weight": 14903,
              "next_doc": 168010,
              "match": 0,
              "build_scorer": 13614558,
              "advance": 0
            }
          }
        ]
      }
    ],
    "rewrite_time": 30804,
    "collector": [
      {
        "name": "MultiCollector",
        "reason": "search_multi",
        "time": "1.529236000ms",
        "children": [
          {
            "name": "TotalHitCountCollector",
            "reason": "search_count",
            "time": "0.08967800000ms"
          },
          {
            "name": "MaxAggregator: [MAX(adj_close)]",
            "reason": "aggregation",
            "time": "0.1675550000ms"
          }
        ]
      }
    ]
  }
]

从profile的结果来看,其原理也是 terms filter(BytesFieldDataTermsQuery)。所以这也就决定了这种join只是伪join。真正的join不仅仅可以用第一个表去filter第二个表,而且要能够在第二个查询的计算阶段引用第一个阶段的结果。这个是仅仅用terms filter无法完成的。当然所有这些join的努力仅仅是让数据维护变得更加容易而已,如果我们真的要求Elasticsearch的join和传统SQL一样强大,那么我们也无法指望那么复杂的join可以快到哪里去,也就失去了使用Elasticsearch的意义了。有了上面两种Join方式,我们可以在极度快速和极度灵活之间获得一定的选择权利。

分享到:
评论

相关推荐

    elasticsearch与hadoop比较

    在数据处理能力方面,Elasticsearch的聚合统计和全文搜索功能虽然强大,但其并不支持SQL中的join或子查询等复杂数据处理操作。Elasticsearch也不支持中间数据输出或数据集转换,因此在处理需要复杂计算逻辑的任务时...

    elasticsearch-sql-2.2.0.1.zip

    5. **JOIN操作**:虽然Elasticsearch本身不支持关系型数据库的JOIN,但Elasticsearch-SQL插件通过巧妙的方式实现了JOIN的效果。 6. **窗口函数**:如LEAD、LAG、RANK等,用于在数据流中进行计算,常用于排名和差异...

    elasticsearch-sql-6.2.2.0.zip

    3. **JOIN操作**:虽然Elasticsearch本身不支持JOIN,但插件可能提供了一种模拟JOIN的方法,比如通过嵌套查询或者多次查询来实现。 4. **Druid连接池兼容**:Druid是一个高性能的数据库连接池,插件与1.1.20版本的...

    elasticsearch-sql-2.4.5.0.zip

    然而,值得注意的是,Elasticsearch并非完全的关系型数据库,因此在处理事务性和复杂JOIN操作时,可能不如传统的RDBMS。此外,由于Elasticsearch的分布式特性,某些SQL功能的实现可能会有所不同,例如分片和复制策略...

    elasticsearch-sql-2.4.3.0.zip 插件 安装包

    此插件的版本为2.4.3.0,提供了与传统关系型数据库相似的交互方式,使那些熟悉SQL语法的用户能够更便捷地在Elasticsearch中进行数据管理。 Elasticsearch本身是一个分布式的、实时的搜索和分析引擎,它以JSON文档为...

    elasticsearch-6.3.2.zip

    这个版本是Elasticsearch的重要里程碑,因为它引入了对SQL查询语法的支持,使得传统数据库用户能够更轻松地过渡到Elasticsearch的生态。 一、Elasticsearch核心概念 1. 文档(Document):Elasticsearch中的基本...

    elasticsearch-sql-master.zip

    4. **JOIN操作**:虽然Elasticsearch本身不支持JOIN操作,但Elasticsearch-SQL提供了一种近似的JOIN实现,通过内嵌查询或脚本字段来实现数据关联。 5. **多索引查询**:用户可以通过一个SQL查询同时操作多个Elastic...

    elasticsearch-sql-5.3.3.0.zip

    而SQL插件的加入,使得Elasticsearch的数据操作更符合传统数据库用户的使用习惯。 在Elasticsearch 5.3.3版本中,SQL插件提供了以下主要功能: 1. **SQL支持**:允许用户通过标准的SQL语句进行索引查询,包括...

    elasticsearch数据的查询sql

    - JOIN: 虽然 Elasticsearch 原生不支持JOIN操作,但可以通过子查询或脚本字段模拟实现类似效果。 - HAVING: 在聚合后过滤,如 `HAVING count(field) &gt; 5`。 - 分页查询: 使用 OFFSET 和 LIMIT 实现分页,如 `...

    elasticsearch-sql-6.2.4.0.zip

    Elasticsearch SQL插件是为Elasticsearch设计的一个强大工具,允许用户通过熟悉的SQL语句来查询、管理和操作Elasticsearch的数据。版本6.2.4.0是这个插件的一个特定发行版,旨在提供更简便的方式来访问和分析存储在...

    elasticsearch-sql插件

    Elasticsearch-SQL插件支持基本的SELECT、FROM、WHERE、GROUP BY、ORDER BY等语句,同时也支持JOIN操作,但需要注意的是,由于Elasticsearch的数据模型与关系型数据库不同,JOIN在性能和实现上有一些限制。...

    Hive+经纬度+数据导入ES

    在大数据处理领域,Hive(Hadoop数据库)常被用于处理结构化数据,而Elasticsearch(ES)则以其强大的全文检索功能著称。在某些应用场景中,需要将Hive中的数据导入到Elasticsearch中进行更高效的数据检索或分析。本...

    hive_elasticsearch_sql面试_大数据面试文档.rar

    在大数据领域,Hive、SQL和Elasticsearch都是至关重要的技术。这些技术在处理大规模数据时发挥着核心作用,尤其在面试过程中,对这些技术的深入理解和应用能力往往是考察求职者的重要标准。以下是对这些技术及其相关...

    elasticsearch 官网 account.json下载

    4. **JSON文档**:Elasticsearch以JSON文档作为数据格式,这与现代Web服务和NoSQL数据库的数据格式相吻合,方便数据的导入和处理。 5. **搜索功能**:ES提供全文检索、结构化查询、近实时分析等多种搜索方式,支持...

    ES-sql-6.3.2 编译好的可直接使用

    标题“ES-sql-6.3.2 编译好的可直接使用”指的是Elasticsearch SQL插件的6.3.2版本,这是一个已经预先编译完成的版本,可以直接应用于Elasticsearch环境中,无需用户自行进行编译过程。Elasticsearch SQL插件允许...

    人大金仓数据库kingbaseESV6SQL参考手册.rar

    另外,《人大金仓_KingbaseES_数据库入门指南for+windoes》可能更侧重于新手上手,提供了在Windows环境下安装、配置KingbaseESV6的步骤,以及基本的数据库操作教程,帮助初学者快速熟悉数据库环境和操作。...

    应对sharding-jdbc结合mybatis实现分库分表功能 分表的联合查询采用将mysql的数据同步到elasticsearch进行筛选

    通过Sharding-JDBC和MyBatis实现数据库分片,结合Logstash将MySQL数据同步到Elasticsearch,解决了分库分表后的联合查询难题,同时利用Elasticsearch的高性能搜索能力,实现了高效的数据筛选。这样的设计思路在大...

    lasticsearch-SQL使用SQL查询Elasticsearch

    6. **JOIN操作**:虽然Elasticsearch不是关系型数据库,但Elasticsearch-SQL提供了跨索引的JOIN操作,使数据分析更为灵活。 7. **前端UI**:Elasticsearch-SQL提供了一个直观的Web界面,用户可以直接在界面上输入...

    远程数据库链接

    ### 远程数据库链接 #### SQL Server 远程数据库链接方法概述 在现代企业环境中,数据经常需要在不同的服务器之间进行交互与共享。SQL Server 提供了多种方式来实现远程数据库连接,包括创建链接服务器(Linked ...

Global site tag (gtag.js) - Google Analytics