ElasticSearch 2 (10) - 在ElasticSearch之下(深入理解Shard和Lucene Index)

摘要

从底层介绍ElasticSearch Shard的内部原理,以及回答为什么使用ElasticSearch有必要了解Lucene的内部工作方式?

  • 了解ElasticSearch API的代价

    • 构建快速的搜索应用
    • 不要任何时候都commit
    • 何时使用Stored Fields和Document Values
    • Lucene可能不是一个合适的工具
  • 了解索引的存储方式
    • term vector是索引大小的1/2
    • 我移除了20%的文件,但是索引占用空间并未发生任何变化

版本

elasticsearch版本: elasticsearch-2.2.0

内容

索引

毫不夸张的说,如果不了解Lucene索引的工作方式,可以说完全不了解Lucene,对于ElasticSearch更是如此。

  • 可以使搜索更快速

    • 可以冗余信息
    • 根据查询(queries)建立索引
  • 在更新速度与查询速度间妥协

    需要注意的是搜索的应用场景

    • Grep vs. 全文检索(full-text indexing)
    • Prefix queries vs. edge n-grams
    • Phrase queries vs shingles

    如果是进行前缀查询(右模糊匹配)或者是短语查询(phrase queries),ElasticSearch可能不合适,需要做特殊的优化。(在2.x中,ES对以上应用场景都有支持,具体使用方式可以参考:Search in Depth

  • Lucene索引的速度

创建索引

以两个简单的文件为例:Lucene in action和Databases。

假设Lucene in action里有单词

{index, term, data, Lucene}

Databases里有单词

{sql, index, data}
  • 树形结构(Tree structure)

    对于range query有序
    查询的时间复杂度为O(log(n))

    一般的关系型数据库大致结构可能是上面这样的一颗B、B+树,但是Lucene是另外一种存储结构。

  • 倒排索引(或反向索引Inverted Index)

    对于Lucene来说,其主要的存储结构是一个反向索引,它是一个数组,数组里面是一个有序的数据字典。

    这样一个存储结构存在与Lucene的Segment里。

    • term ordinal —— 是一个词的序号
    • term dict —— 是词的内容
    • postings list —— 存放包含词的文件的id序列
    • doc id —— 是每个文件的唯一标识
    • document —— 存放每个文件的内容

    这两种结构的一个重要区别是:在增加或删除文件时,系统会树形结构频繁操作,这个结构是一直变化的,而反向索引可以维持不变(Immutable)。

  • 插入?

    • 插入 即 创建一个新的segment
    • 当有很多segment时,系统会合并segment
      这个过程本质上是一个merge sort,做的事情就是
      • 连接文件
      • 合并字典
      • 合并postings lists

  • 删除?

    • 删除要做的只是置一个标志位
    • 搜索及merge的时候系统会忽略被删除的文件
    • 当有很多删除发生时,系统会自动运行merge
    • 被标记为已删除的文件会在merge完成后回收其所占用的存储空间

  • 孰优孰劣?

    • 当更新一个文件的时候,我们实际上是创建了一个新的segment,因此

      • 单个文件的更新代价高昂,我们需要使用bulk更新
      • 所有的写操作都是顺序执行的
    • Segments永远不会被修改
      • 文件系统缓存友好
      • 不会出现锁的问题
    • Terms 高度去重
      • 节省大量高频词所占用的空间
    • 文件本身由唯一序号标识
      • 跨API通信的时候非常方便
      • Lucene可以在单个Query下使用多个索引index
    • Terms 由唯一序号标识
      • 对于排序非常重要,只需要比较数字,而非字符串
      • 对于faceting(分面搜索)非常重要
  • Lucene Index的强大之处(Index intersection)

    很多数据库不支持同时使用多个索引,但是Lucene支持

    • Lucene为postings lists 维护一个skip list(Wiki),如果要搜索如上例子中的“red shoe”,系统参考skip list里的信息可以跳跃检索(“leap-frog”)
    • 对于很多数据库,它们会挑选最主要的索引(most selective),而忽略其他

    关于详细的index intersection算法以及如何使用skip list的可以参照(nlp.standford.edu

更多索引

  • 术语向量(Term vectors)

    • 为每个文件都会创建一个反向索引(Inverted Index)
    • 适用场景:搜索更相似的内容
    • 也可以用作高亮搜索结果

  • 文件值(Document Values)

    • 以文件字段为单位进行列式存储
    • 适用场景:排序、权重记分

  • 有序(集合)文件值

    • 文件有序、字段有序

      • 单字段:排序
      • 多字段:分面搜索

  • 分面搜索(Faceting)

    分面是指事物的多维度属性。例如一本书包含主题、作者、年代等分面。而分面搜索是指通过事物的这些属性不断筛选、过滤搜索结果的方法。可以将分面搜索看成搜索和浏览的结合。分面搜索作为一种有效的搜索方式,已经被用在电子商务、音乐、旅游等多个方面。

    例如,谷歌音乐的挑歌页面,将歌曲分为节奏、声调、音色、年代、流派等分面

    • 根据文件与搜索匹配的情况计数

      • 例如,电商网站根据衣服的款式、衣长、尺码、颜色等分面。
    • 简单(naive)方案
      • 利用哈希表计数(value to count)
      • O(#docs) ordinal 查找
      • O(#doc) value 查找
    • Lucene方案
      • 哈希表(ord to count)
      • 最后统计值
      • O(#docs) ordinal 查找
      • O(#values) value 查找

    因为ordinal是密集的,所以可以简单用数组array来表示。

  • 如何使用API?

    ElasticSearch高级API 都是基于Lucene API构建的,这些基础的API包括:

    -----------------------------------------------------------------------------------------------
        API                 |   用途                                  |   方法
    -----------------------------------------------------------------------------------------------
        Inverted index      | Term -> doc ids, positions, offsets   |   AtomicReader.fields
    -----------------------------------------------------------------------------------------------
        Stored fields       | Summaries of search results           |   IndexReader.document
    -----------------------------------------------------------------------------------------------
        Live docs           | Ignoring deleted docs                 |   AtomicReader.liveDocs
    -----------------------------------------------------------------------------------------------
        Term vectors        | More like this                        |   IndexReader.termVectors
    -----------------------------------------------------------------------------------------------
        Doc values/Norms    | Sorting/faceting/scoring              |   AtomicReader.get*Values
    -----------------------------------------------------------------------------------------------     
  • 小结

    • 数据有四份重复,只是结构各不相同

      • 绝不是浪费空间
      • 感谢immutable使数据易于管理
    • Stored Fields和Document Values
      • 两种结构为不同的使用场景优化

        1. 少量文件获取多个字段:Stored Fields
        2. 大量文件获取少量字段:Document Values

文件格式的秘密

  • 不能忘的规则

    • 保存文件的句柄

      不要为每个字段每个文件使用文件

    • 避免磁盘寻址

      磁盘寻址的时间大概为~10ms

    • 不要忽略文件系统的缓存

      随机访问小文件还是可以的

    • 使用轻压缩
      • 更少I/O
      • 更小索引
      • 文件系统缓存友好
  • 编码解码

  • 合适的压缩技术

    • Bit packing / vlnt encoding

      • postings lists
      • numeric doc values
    • LZ4
    • FSTs
      • Map<string, ?="">
      • 键共享前缀(prefix)和后缀(suffix)
      • terms index
  • TermQuery的背后

    1. Terms Index

      在索引中查找相应的词

      • 在内存中FST存储了词的前缀prefix
      • 提供词在字典中的偏移量
      • 在不存在时可以快速失败

    2. Terms Dictionary
      • 跳到字典偏移的位置

        压缩是基于共享前缀的,与“BlockTree term dict”类似

      • 顺序读取直到找到特定的Term

    3. Postings List
      • 跳到postings list偏移量对应位置
      • 用改进的FOR(Frame of Reference)进行增量编码
        1. 增量编码
        2. 将块拆分为N=128个值的大小
        3. 每个块使用位压缩(bit packing)
        4. 如果有剩余文档,使用vlnt压缩

    4. Stored Fields
      • 对一个子集的doc id,索引存于内存中

        高效内存(monotonic)压缩

        二分查找

      • 字段

        顺序存储

        使用16KB块存储压缩

  • 查询过程小结

    • 每个字段2次磁盘寻址
    • 每个文件1次磁盘寻址(Stored Fields)
    • terms dict/postings lists都在文件系统的缓存中

      此时不会发生磁盘寻址

    • “脉冲”优化
      • 对于唯一的term,postings list存储在Terms dict中
      • 1次磁盘寻址
      • 永远作为主键

性能

上图中系统性能出现两次下降,可能的情况是

  1. 索引增长超过文件系统缓存的大小

    Stored Fields不再全部存储于缓存中

  2. Terms dict/Postings lists不全在缓存中

参考

参考来源:

SlideShare: What is in a Lucene index?

Youtube: What is in a Lucene index? Adrien Grand, Software Engineer, Elasticsearch

SlideShare: Elasticsearch From the Bottom Up

Youtube: Elasticsearch from the bottom up

Wiki: Document-term matrix

Wiki: Search engine indexing

Skip list

Standford Edu: Faster postings list intersection via skip pointers

分面搜索(Faceted Search)

StackOverflow: how an search index works when querying many words?

StackOverflow: how does lucene calculate intersection of documents so fast?

Lucene and its magical indexes

结束

时间: 2024-10-08 20:18:00

ElasticSearch 2 (10) - 在ElasticSearch之下(深入理解Shard和Lucene Index)的相关文章

Windows 10 安装ElasticSearch(2)- MSI安装ElasticSearch和安装Kibana

翻阅上篇文章:Windows 10 安装 ElasticSearch 上次写的是下载Zip包安装的,在下载页面 发现有 MSI (BETA) 的下载可选项.了解之后发现MSI安装也值得尝试. MSI安装ElasticSearch 参考文章:Install Elasticsearch with Windows MSI Installer 与zip包安装相比,MSI安装可以将ElasticSearch作为Windows 服务安装,这样可以方便设置开机自启动,就不用看到有一个cmd命令行在任务栏,El

elasticsearch系列一:elasticsearch(ES简介、安装&amp;配置、集成Ikanalyzer)

一.ES简介 1. ES是什么? Elasticsearch 是一个开源的搜索引擎,建立在全文搜索引擎库 Apache Lucene 基础之上 用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API. Elasticsearch 不仅仅只是一个全文搜索引擎. 它可以被下面这样准确的形容: 一个分布式的实时文档存储,每个字段可以被索引与搜索--作数据库用 一个分布式实

ElasticSearch实战系列四: ElasticSearch理论知识介绍

前言 在前几篇关于ElasticSearch的文章中,简单的讲了下有关ElasticSearch的一些使用,这篇文章讲一下有关 ElasticSearch的一些理论知识以及自己的一些见解. 虽然本人是一个实战派,不太喜欢讲这些理论知识,因为这块可以查看官方文档,那里会写得非常详细,但是在使用了ElasticSearch之后,发现有的知识点需要掌握一定的理论知识才能理解,对于初学者来说有的不好理解,因此写下该篇文章,希望读者在看完之后能够有所帮助. ElasticSearch 理论知识介绍 Ela

2014年去哪儿网笔试题--一个10*10的矩阵(可以理解为棋盘),随时生成一组数据填入矩阵,任何一个位置的数字除4进行计算,按余数着色...

一个10*10的矩阵(可以理解为棋盘),随时生成一组数据填入矩阵,任何一个位置的数字除4进行计算,按余数着色,余数为0着色为red,1为blue,2为green,3为black,可以理解为生成4中颜色的棋子放入棋盘,如果存在其中同色五星连珠的情况(规则通五子棋),找出任意一组,输出5个棋子的位置下标值. 只是用最笨的方法实现一下: public class FiveColor { public void test(){ int a[][]=new int[10][10]; for(int i=0

【SpringBoot整合Elasticsearch】SpringBoot整合ElasticSearch

一.Linux下安装ElasticSearch 1.检测是否安装了Elasticsearch 1 ps aux |grep elasticsearch 2.安装JDK 3.下载Elasticsearch 1 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0.tar.gz 解压Elasticsearch tar -zxvf elasticsearch-6.0.0.tar.gz 移动Elasti

ElasticSearch实战系列一: ElasticSearch集群+Kinaba安装教程

前言 本文主要介绍的是ElasticSearch集群和kinaba的安装教程. ElasticSearch介绍 ElasticSearch是一个基于Lucene的搜索服务器,其实就是对Lucene进行封装,提供了 REST API 的操作接口. ElasticSearch作为一个高度可拓展的开源全文搜索和分析引擎,可用于快速地对大数据进行存储,搜索和分析. ElasticSearch主要特点:分布式.高可用.异步写入.多API.面向文档 . ElasticSearch核心概念:近实时,集群,节点

Windows 10 安装 ElasticSearch

Java环境准备 可以下载oracle最新的JDK,作为C#程序员,支持一下微软的Mobile OpenJDK,构建一下Java环境. 微软的OpenJDK是针对Xamarin.Android的SDK,在我尝试之前不确定是否适用ElasticSearch.结论是:没问题. Microsoft 分发的 Mobile OpenJDK:https://docs.microsoft.com/zh-cn/xamarin/android/get-started/installation/openjdk 下载

【好文】ElasticSearch 5学习——安装Elasticsearch、Kibana和X-Pack

安装准备: 安装Elasticsearch唯一的要求是安装官方新版的Java,包括对应的Jdk. 安装Elasticsearch 首先到官网下载最新版本的Elasticsearch压缩包. 可以使用命令,注意将最新的可用的下载链接填入: curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0.2.zip unzip elasticsearch-5.0.2.zip cd elasticsea

elasticsearch(5) curl 操作elasticsearch

创建索引之前可以对索引做初始化操作, 比如指定shards数量以及replicas的数量.     library为索引的名称 CURL -XPUT 'http://192.168.1.10:9200/library/' -d '{ "settings": { "index": { "number_of_shards": 5, "number_of_replicas": 1 } } }' CURL -XGET 'http://