ElasticSearch基础及面试问答知识点

一、ES介绍:

  • ES是一款基于倒排索引的NoSQL数据库,传统数据库对于模糊查询存在性能瓶颈,ES更擅长于大数据量的模糊查询,搜索场景下
  • ES存数据时,会先将数据进行分词,将分词的结果作为索引存入数据库中;当进行查询时也会将查询的参数进行分词,根据分词结果去ES中查询索引,根据索引查找到匹配的文档,从而将文档返回

二、请求方式:

  • MySQL:数据存储在表中,表存储在数据库中
  • ES:document存储在Type中,type存储在index中
    • index:相当于数据库
    • type:相当于表
    • docment:相当于数据库中的一条数据
    • field text/keyword/byte:相遇于列
    • 映射Mapping:Schema
    • 分片sharding和副本replicas:index都是由sharding组成的,每个sharding都有一个或多个备份
    • shard 分片数量在建立索引时设置,设置后不能修改,默认5个;replica 副本数量默认1个,可随时修改数量

三、基本操作

MySQL:数据库 -> 数据表 -> 数据 ES:index -> type -> document

  • 索引 (表)

    • 创建 – PUT index_name
    • 删除 – DELETE index_name
    • 查询 – GET index_name
  • 文档 (数据):对数据的操作需要先找到Index再找到type再找到文档编号,文档编号类似于MYSQL中的主键

    1. 添加 – POST index_name/_doc/101

    2. 删除 – DELETE index_name/_doc/101

      不会物理删除,只会将其标记为deleted,当数据越来越多时,在后台自动删除

    3. 修改 – POST index_name/_doc/101

      全量修改、部分更新(脚本修改、文档合并等)

      修改数据和添加数据相同,若不存在该数据,则会创建一条数据;存在该数据,则进行全量替换,替换document的json串内容

      document是不可变的,如果要修改document的内容,就要进行全量替换,直接对document重新创建索引,替换里面的内容

      es会把之前的document标记为deleted,然后新增给定的document,当创建越来越多,es会在后台自动删除标记为deleted的document

    4. 查询 – GET index_name/_doc/101

四、复杂查询

  • 精确查询

    • term 不对关键字进行分词,进行全匹配

      GET /index1/_search
      {
        "query":{
          "term":{
            "item": "1001"
          }
        }
      }
      
    • terms 多关键词全匹配

      GET /index1/_search
      {
        "query":{
          "terms":{
            "item": ["1001","1002","1003"]
          }
        }
      }
      
  • 模糊查询

    • match 对关键词进行拆词匹配

      GET /index1/_search
      {
        "query":{
          "match":{
            "itemName": "花瓶"
          }
        }
      }
      
    • match_all 对所有关键词进行拆词匹配

    • multi_match 多属性匹配

      GET /index1/_search
      {
        "query":{
          "multi_match":{
            "query": "类别",
            "fields": ["itemName","itemPrice"]
          }
        }
      }
      
  • 分页查询

    GET /index1/_search
    {
      "query":{
        "match":{
          "itemName": "花瓶"
        }
      },
      "from":0,
      "size":3
    }
    
  • 排序 “order”:“asc/desc”

    GET /index1/_search
    {
      "query":{
        "match":{
          "itemName": "花瓶"
        }
      },
      "from":0,
      "size":3,
      "sort": [
        {
          "itemPrice": {
            "order": "asc"
          }
        }
      ]
    }
    
  • 范围查询 – gte lte

    GET /index1/_search
    {
      "query":{
        "range": {
          "itemPrice": {
            "gte": 5,
            "lte": 20
          }
        }
      }
    }
    
  • 模糊查询 – “fuzzy”:{}

    GET /index1/_search
    {
      "query":{
       "fuzzy": {
         "itemName": {
           "value": "瓶"
         }
       }
      }
    }
    
  • 复合查询 must->and should->or must_not->not

    在查询数据时,复合条件的文档会通过_source字段返回数据

    GET index1/_search
    {
      "query": {
        "bool":{
          "must": [
            {
              "match": {
                "itemName": "花瓶"
              }
            }
          ]
        }
      },
      "sort": [
        {
          "itemPrice": {
            "order": "asc"
          }
        }
      ],
      "_source": ["itemPrice","itemName"], 
      "from": 0,
      "size": 5,
      "highlight": {
        "fields": {
          "itemName": {}
        },
        "pre_tags": "aaaa",
        "post_tags": "ddddd"
      }
    }
    

五、面试相关知识

  • source字段会存储文档的原始信息,在查询复合条件的文档时,会通过_source字段返回原始信息;但有时并不需要source字段,不使用能节省不少的存储空间;以下几种情况必须有source:

    1. 文档需要使用update或update_by_query更新
    2. 会用到reindex
    3. 会用到文档高亮
  • ES:是一个基于Lucene框架的搜索引擎产品,提供Restful风格的操作接口

    • Lucene是一个非常高效的全文检索引擎框架
  • 倒排索引:索引是从ID到内容,倒排索引是从内容到ID。比较适合做关键字检索,可以控制数据总量,提高查询效率。如:根据输入的某个单词,找到含有这个单词,或与这个单词有关的文章

    • 倒排索引中,所有词项对应一个或多个文档
    • 倒排索引中的词项,根据字典排序升序排列
  • text和keyword类型的区别:keyword类型是不会分词的,直接根据字符串内容建立倒排索引,所以keyword类型的字段只能通过精确值搜索;text类型在存入es时,回显分词,然后根据分词后的内容建立倒排索引

  • query和filter的区别:query查询操作不仅会进行查询,还会计算分值,用于确定相关度;filter:查询操作仅判断是否满足查询条件,不会计算分值,也不关心返回的排序问题,同时filter查询的结果可以被缓存,提高性能

  • ES写入数据的工作原理

    1. 客户端发写数据的请求时,可以发往任意节点,这个节点就会成为协调节点
    2. 计算文档要写入的分片:计算时采用hash取模的方式进行
    3. 协调节点会进行路由,将请求转发给对应的primary sharding所有的数据节点
    4. 数据节点上的primary sharding处理请求,写入数据到索引库,并将数据同步到对应的replica sharding
    5. primary sharding和replica sharding都保存好文档后,返回客户端响应
  • ES的更新和删除流程

    • 由于ES中的文档是不可变的,因此不能被删除或修改
    • 如果是删除,文档其实并没有被删掉,而是在.del文件中被标记为deleted状态,该文档亦然能匹配,但在结果中会被过滤
    • 如果是更新,就是将 旧得doc标识为deleted状态,然后创建一个新的doc
      • memory buffer每refresh一次,就会产生一个segment文件,所以默认1s生成一个segment,定期执行merge,将多个segment文件合并成一个,同时会将标识为deleted的doc给物理删除掉,不写入新的segment。然后会写一个commit point标识所有新的segment文件供搜索使用,删除旧的
  • ES查询数据的工作原理

    1. 客户端发请求给任意一个节点,这个节点就称为协调节点
    2. 协调节点将查询请求广播到每一个数据节点,这些数据节点的分片就会处理该查询请求
    3. 每个分片进行数据查询,将符合条件的数据放在一个队列中,并将这些数据的文档ID、节点信息、分片信息都返回给协调节点
    4. 由协调节点将所有结果进行汇总并排序
    5. 协调节点向包含这个文档ID的分片发送get请求,对应的分片将文档数据返回给协调节点,最后协调节点将数据整合返回给客户端

    总结:客户端将请求发动到协调节点,协调节点将请求广播到数据节点,数据节点的分片进行数据查询,返回结果进行汇总并排序,协调节点向包含文档ID的分片发送get请求,得到文档数据后,整合返回给客户端

  • ES的搜索流程

    • Query – 协调节点将搜索请求广播到所有的primary shared或replica,每个分片在本地执行搜索并构建一个匹配文档大小的优先队列。接着每个分片返回各自优先队列中 所有docId和打分值给协调节点,由协调节点进行数据合并、排序、分页等,产生最终结果
    • Fetch – 协调节点根据Query 阶段产生的结果,在各个节点上查询docId实际的document内容,最后由协调节点返回结果给客户端
    • summary:协调节点根据分片执行搜索返回的结果进行数据合并、排序、分页等并产生Query 结果;根据Query 结果查询docId实际的document内容返回给客户端
  • ES的深度分页与滚动搜索scroll

    • 深度分页:其实就是搜索的深浅度,如1-10页是比较浅的,第10000/20000页就是很深的了。搜索太深就会造成性能问题,es为了性能,不支持超过一万条数据以上的分页查询,因此应该避免深度分页操作(限制分页页数),比如最多只提供100页展示
    • 滚动搜索:一次查询1万+条数据,往往会造成性能相应。此时可使用滚动搜索scroll,滚动搜索可以先查询出一些数据,再接着依次往下查询。在第一次查询时会有一个滚动id,相当于一个锚标记,随后再次滚动搜索会需要根据上一次搜索滚动id,进行下一次的搜索请求。
  • ES在高并发下如何保证读写一致

    • 对于更新操作 – 可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖
      • 每个文档都有一个_version,在文档被修改时,该值加1,当一个旧版本出现在新版本之后,会被简单忽略。_version确保数据不会因为修改冲突而丢失
      • 比如指定文档version进行修改,如果版本号不对,请求失败
    • 对于写操作 – 一致性级别支持quorum/one/all,默认为quorum 但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样的副本被认为故障,副本会在不同节点上重建
      • quorum – 要求ES中大部分的shard是活跃可用的,才可以执行写操作
      • one – 写操作只要有一个primary shard是active活跃可用的,就可以执行
      • all – 写操作必须所有的primary shard和replica shard都是活跃可用的,才可以执行
    • 对于读操作 – 可以设置 replication 为 sync(默认),使得操作在主分片和副分片都完成后才会返回;如果设置replication 为 async 时,也可以通过设置搜索请求参数 _preference 为 primary 来查询主分片,确保文档是最新版本
  • 建立索引阶段性能提升方法

    1. 大批量导入时,设置 index.number_of_replicas: 0 关闭副本,等数据导入完成后再开启
    2. 使用批量请求并调整大小:每批数据5-15MB
    3. 如果搜索结果不需要近实时性,可以把每个索引 index.refresh_interval 改到30s
    4. 增加index.translog.flush_threshold_size 设置,从默认的512MB到更大的值
    5. 使用 SSD 存储介质
    6. 端和合并:Elasticsearch 默认值是 20 MB/s,如果是SSD,可以考虑提高到100-200MB/s。如果在做批量导入,可以彻底关掉合并限流
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值