【Java劝退师】Elasticsearch 知识脑图 - 分布式全文检索引擎

912 阅读8分钟

Elasticsearch

Elasticsearch

分布式全文检索引擎

一、使用场景

  1. 信息搜索
    • 电商网站
    • 求职网站
    • 新闻网站
  2. 日志收集、分析 - ELK
  3. 数据分析 - 商品销量、访问量、消费金额

二、核心概念

  1. Index 索引 - Database 数据库
  2. Shard 索引分片
    • 一个 Shard 对应一个 Lucene 的 Index
    • 一个 Shard 都有一个 translog
  3. Type 类型 (即将废除) - Table 表
  4. Document 文档 - Row 数据行
  5. Field 字段 - Column 字段
  6. Mapping 映射 - Scheme 字段约束

三、API

URL 加上 ?explain 可以查看语句错误原因

1. Index 索引

  • 创建索引 - PUT /索引名称
  • 判断索引是否存在 - HEAD /索引名称
  • 查看索引属性
    • 单个 - GET /索引名称
    • 多个 - GET /索引名称1,索引名称2,索引名称3
    • 所有 - GET _all
    • 所在分片状态 - GET /_cat/indices?v
  • 启用索引 - POST /索引名称/_open
  • 关闭索引 - POST /索引名称/_close
  • 删除索引 - DELETE /索引名称1,索引名称2,索引名称3
  • 索引迁移 - POST _reindex
    • version_type
      • 【默认】internal - 直接迁移,碰到已存在文档则进行覆盖
      • external - 保留 version 信息迁移,碰到已存在文档对 version 进行更新
    • op_type
      • create - 碰到已存在文档,提示错误
    • conflicts
      • proceed - 碰到已存在文档,错误消息提示,只提示文档冲突数量
    • query - 支持 数据过滤、排序、数量 设置

2. Mapping 映射

  • 创建映射 - PUT /索引名称/_mapping
PUT /索引库名/_mapping
{
    "properties": {
        "字段名": {
            "type": "类型",
            "index": true"store": true"analyzer": "分词器"
        }
    }
}
PUT /lagou-company-index/_mapping/
{
    "properties": {
        "name": {
            "type": "text",
            "analyzer": "ik_max_word"
        },
        "job": {
            "type": "text",
            "analyzer": "ik_max_word"
        },
        "logo": {
            "type": "keyword",
            "index": "false"
        },
        "payment": {
       		"type": "float"
        }
    }
}
  • 查看映射关系 - GET /索引名称/_mapping

  • 查看所有映射关系

    • GET _mapping
    • GET all/_mapping
  • 修改映射关系 - PUT /索引名称/_mapping

    • 只能增加映射字段,不能更改
    • 如需更改,只能删除重建映射
  • 同时创建索引及映射关系 - PUT /索引名称

3. Document 文档

  • 添加文档

    • 指定 ID - POST /索引名称/_doc/{id}
    • 自动生成 ID - POST /索引名称/_doc
  • 查看文档

    • ID 查找 - GET /索引名称/_doc/{id}
    • 条件查找 - GET/索引名称/_search
    • 返回属性过滤 - GET /索引名称/_doc/{id} ?_source=属性1,属性2
  • 更新文档

    • 全局更新(原数据删除后添加) - PUT /索引名称/_doc/{id} - id 不存在则添加
    • 局部更新(修改单一字段) - POST /索引名称/_update/{id}
  • 删除文档

    • 指定 ID - DELETE /索引名称/_doc/{id}
    • 条件过滤 - POST /索引名称/_delete_by_query
  • 批量查找

    • GET /_mget
    • GET /索引名称/_mget
  • 批量增、删、改 - POST /_bulk {"方法": { "_index" : "索引名称", "_id" : "id编号"}} {"data"}

    • create - 添加文档

    • index - 添加文档、全文替换文档 - 相当于 PUT

    • update - 局部更新文档

    • delete - 删除文档

    建议一次更新 1000 ~ 5000 个文档,大小 5 ~ 15 M

四、Mapping 属性

  • type 类型

    • String 字符串

      • text - 分词,不可聚合
      • keyword - 不分词,可聚合
    • Numberical 数值

      • byte
      • short
      • interger
      • long
      • double
      • float
      • half_float
      • scaled_float - 高精度,需指定精度因子
    • Date 日期 - 【建议】使用 long 保存毫秒值

    • Array 数组

      • 匹配时,数组中任一元素满足,则认为满足
      • 排序时,升序使用数组中最小元素排序,降序使用数组中最大元素排序
    • Object 对象

    • geo_point 经纬度

  • index 是否索引 - 是否可用于搜索 - 【默认】true

  • store 是否存储 - 数据是否独立存储,加快解析速度,但费空间 - 【默认】false

  • analyer 分词器

    • 中文
      • ik_max_word【常用】 - 最细粒度
      • ik_smart - 最粗粒度
  • dynamic 动态(遇到陌生字段)映射方式

    • true - 自动映射
    • false - 忽略
    • strict - 报错
  • date_detection 是否关闭日期检测 - 设为 false 时,字符串将始终为 string 类型

  • dynamic_date_formats 设置字符串转换日期规则

  • dynamic_templates 不同字段或数据类型,使用不同的映射

  • refresh_interval 索引刷新频率 - 【默认】1秒

  • index.translog.durability translog 刷盘方式 - 【默认】sync

  • index.translog.sync_interval translog 刷盘间隔 - 【默认】 5秒

PUT /索引库名称
{
    "settings":{
        "number_of_shards": 分片数量,
		"number_of_replicas": 副本数量,
        "refresh_interval": "索引刷新频率",
        "index.translog.durability": "async",
		"index.translog.sync_interval": "5s"
    },
    "mappings":{
        "dynamic": "动态映射方式",
        "date_detection": 是否关闭日期检测,
        "dynamic_date_formats": "MM/dd/yyyy",
        "properties":{
            "字段名":{
            	"映射属性名":"映射属性值"
            }
        },
    }
}

五、查找类型

POST /索引库名/_search
{
    "query":{
        "查找类型":{
        	"查找条件":"查找条件值"
        }
    },
    "sort": [
    	{"要排序的字段": {"order": "asc"}}
    ],
    "highlight": {
        "pre_tags": "<font color='pink'>",
        "post_tags": "</font>",
        "fields": [{"要高亮的字段":{}}]
    },
    "from": 当前页数,
    "size": 每页条数	
}
  • match_all - 查找所有

  • match - 将查找条件分词查找,词条间关系为 or - 改为 and 需使用 operator 属性

  • match_phrase - 将查找条件分词,目标文档需包含所有分词且顺序一致

  • multi_match - 将查找条件分词查找,词条间关系为 or,可指定查找 field

    • 可使用 * 描述 field - *_name
    • 可使用 ^ 加强 field 权重 - subject^3
  • term - 不分词查找

  • query_string - 可指定字段或全文搜索,可使用 AND、OR、~ 操作符切分字符串

  • range - 范围查找,用于查找数字、日期

  • exists - 非空查找

  • prefix - 前缀匹配查找

  • wildcard - 通配符查找

  • regexp - 正则查找

  • fuzzy - 模糊查找

  • bool - 复合查找

    • must - 必须包含
    • filter - 必须包含,不影响评分,会被缓存到内存,重复查找速度加快
    • should - 应该包含
    • must_not - 必须不包含,不影响评分
  • dis_max - 多个搜索域分数,只取最高分作为评分 - 默认多个搜索域分数相加

  • suggest - 建议查找

    • completion - 查找条件前缀匹配,给出建议

    • preserve_separators - 查找条件是否保留分割符

      • preserve_position_increments - 当建议词的第一个词是停用词时,是否忽略停用词
    • phrase - 将查找条件分词后,判断与原文的匹配程度给出建议

    • term - 将查找条件进行分词,并为每个词条给出建议

      • missing - 当词条在词典中找不到,才给出建议
      • always - 不论词条在词典中是否找到,都给出建议
      • popular - 不论词条在词典中是否找到,都给出词频更高的建议
    • context - 与 completion 相似,增加类别进一步过滤

    生产建议 :

    completion → 零匹配 → phase → 零匹配 → term

六、聚合分析

"aggregations" : {
    "<aggregation_name>" : { <!--聚合的名字 -->
        "<aggregation_type>" : { <!--聚合的类型 -->
       		<aggregation_body> <!--聚合体:对哪些字段进行聚合 -->
        }
    	[,"meta" : { [<meta_data_body>] } ]? <!--元数据 -->
        [,"aggregations" : { [<sub_aggregation>]+ } ]? <!--在聚合里面在定义子聚合 -->
    }
	[,"<aggregation_name_2>" : { ... } ]*<!--聚合的名字 -->
}

1. 统计方式

  • 指针聚合 metric
  • 桶聚合 bucketing - 先对数据进行分组,再进行聚合统计

2. 统计指针

  1. 最大值 max
  2. 最小值 min
  3. 和 sum
  4. 平均值 avg
  5. 计数 count
  6. 文档字段有值计数 value_count
  7. 去重计数 cardinality
  8. 基本统计 stats - 包含 max、min、sum、avg、count
  9. 高级统计 extended_stats - 包含 平方和、方差、标准差
  10. 百分占比统计 percentiles - 可指定百分位
  11. 区间百分比统计 percentile_ranks

七、分布式集群

1. 角色

  • Cluster 集群 - 多个 Node 组成,集群中的每个 Node 都有一个共同的集群名称作标示
  • Node 节点
    • master - 是否有资格竞选主节点 - 【默认】 true
    • data - 是否保存数据 - 【默认】 true
  • Shard 分片 - 索引的数据分块
    • 主分片数量不可变,除非重建索引
    • 默认每个主分片都有一个副本分片,且两个分片不在一个节点上

2. 特色

  • 新节点自动发现
  • 节点对等 - 每个节点都能接收请求,接收请求后将请求转发到存放数据的其它节点上
  • 当节点当机,透过副本分片对缺失数据进行恢复
  • 搜索时间百毫秒内

3. 搭建规划

原则

  • 30G JVM 内存,分片最大容量设为 30G,再根据数据量推算总分片数量 【主分片数量不可变,除非重建索引】

  • 总分片数量 除 1.5 ~ 3 为 节点数量

  • 副本数量 2,保证高可用

  • 当查找性能下降,可增加副本数,提高并发查找能力

应用

  • 搜索功能 - 数据量 千万 ~ 十亿 - 2~4个节点

  • 联机处理分析 - ELK - 数据量 千亿 - 几十~上百个节点

4. 一致性保证

  • ?wait_for_active_shards=同步分片数量&timeout=超时时长

八、关联关系

  1. Application-side join 应用连接 - 索引之间独立 - 适用少量文档纪录
  2. Data denormalization 非规范化嵌套文档、Nested objects 嵌套文档
    • 透过字段冗于,牺牲索引性能换取查找性能
    • 冗于字段应很少改变
    • 适合少量关系处理
    • 适用读多写少场景
  3. Parent/child relationships 父子文档
    • 牺牲查找性能换取索引性能
    • 查找不能同时返回父子文档
    • 父子文档必须在同一分片上
    • 适用写多读少场景

九、持久化

  1. refresh

    • 将内存 buffer 写入到一个新的 segment 中,使索引变成可检索状态
    • 【默认】每 1 秒运行一次
  2. flush

    • 将所有 segment 刷盘,并清空 translog 日志,并创建提交点

    • 【默认】每 30 分钟运行一次

    当节点崩溃并重启时,将从提交点重放 translog 日志,以恢复数据

十、并发控制

  1. 内置版本号 - ?if_seq_no=版本号&if_primary_term=1
  2. 自定义版本号 - ?version=版本号&version_type=external

十一、分页方案

  1. from + size - 常用分页方法,深度分页会出现性能问题
  2. scroll - 将所有符合条件的搜索结果缓存起来 - 不适合实时搜索,适合后台批处理
  3. search after - 根据上一页最后一条数据确定下一页位置 - 不能跳页

十二、性能优化

  1. 首次灌入数据,副本数设置为 0
  2. 自动生成 doc ID,避免读盘操作
  3. 不重要字段 不分词、不索引
  4. 调整索引刷新时间间隔 - 默认 1 秒