Elasticsearch 倒排索引 和 正排索引
一、倒排索引
倒排索引是 Elasticsearch 实现高效全文搜索的核心技术。它通过将词项与文档 ID 关联,支持快速检索、短语查询、布尔查询和相关性评分。尽管倒排索引在存储和更新方面有一定的开销,但通过词典优化、倒排列表压缩、分片和缓存等技术,Elasticsearch 能够高效地处理大规模数据的搜索需求。
1.1 倒排索引的结构
倒排索引的核心是:词典(Term Dictionary) 和 倒排列表(Posting List)。
- 词典(Term Dictionary):
- 作用:存储所有文档中出现的词项(Terms),并按字典序排序。
- 特点:
- 支持快速查找某个词项是否存在。
- 存储词项的元数据,如文档频率(Document Frequency, DF)。
- 数据结构:
- 通常使用 FST(Finite State Transducer) 存储,支持高效的前缀查找和范围查询。
- 倒排列表(Posting List):
- 作用:记录包含某个词项的所有文档及其相关信息。
- 内容:
- 文档 ID(DocID):标识包含该词项的文档。
- 词频(Term Frequency, TF):词项在文档中出现的次数。
- 位置信息(Positions):词项在文档中的具体位置(用于短语查询或高亮显示)。
- 偏移量(Offsets):词项在文档中的起始和结束位置(可选)。
- 存储优化:
- 使用 差值编码(Delta Encoding) 压缩文档 ID 和位置信息。
- 使用 FOR(Frame of Reference) 或 RLE(Run-Length Encoding) 等压缩算法减少存储空间。
示例:
-
文档内容
- 文档 1:“Elasticsearch is powerful”
- 文档 2:“Elasticsearch is fast and powerful”
-
分词结果
经过分词和标准化处理后,生成的词项(Terms)如下:- 文档 1 的词项:[“elasticsearch”, “is”, “powerful”]
- 文档 2 的词项:[“elasticsearch”, “is”, “fast”, “and”, “powerful”]
-
倒排索引结构
-
词典(Term Dictionary)
词典存储所有词项及其元数据(如文档频率):词项(Term) 文档频率(DF) “and” 1 “elasticsearch” 2 “fast” 1 “is” 2 “powerful” 2 -
倒排列表(Posting List)
每个词项对应一个倒排列表,记录包含该词项的文档及其相关信息(如文档 ID、词频、位置信息、偏移量等)。- 词项 “elasticsearch”
文档 ID(DocID) 词频(TF) 位置信息(Positions) 偏移量(Offsets) 1 1 [0] [(0, 13)] 2 1 [0] [(0, 13)] - 词项 “is”
文档 ID(DocID) 词频(TF) 位置信息(Positions) 偏移量(Offsets) 1 1 [1] [(14, 16)] 2 1 [1] [(14, 16)] - 词项 “powerful”
文档 ID(DocID) 词频(TF) 位置信息(Positions) 偏移量(Offsets) 1 1 [2] [(17, 25)] 2 1 [4] [(27, 35)] - 词项 “fast”
文档 ID(DocID) 词频(TF) 位置信息(Positions) 偏移量(Offsets) 2 1 [2] [(17, 21)] - 词项 “and”
文档 ID(DocID) 词频(TF) 位置信息(Positions) 偏移量(Offsets) 2 1 [3] [(22, 25)]
- 词项 “elasticsearch”
-
压缩与存储优化
在实际存储中,Elasticsearch 会对倒排列表进行压缩和优化:- 文档 ID:使用差值编码(Delta Encoding)压缩。例如,文档 ID [1, 2] 存储为 [1, 1](差值)。
- 位置信息:使用差值编码压缩。例如,位置信息 [0, 1, 2] 存储为 [0, 1, 1](差值)。
- 偏移量:使用差值编码压缩。
-
完整倒排索引结构
{"terms": {"and": {"doc_freq": 1,"postings": [{"doc_id": 2,"term_freq": 1,"positions": [3],"offsets": [(22, 25)]}]},"elasticsearch": {"doc_freq": 2,"postings": [{"doc_id": 1,"term_freq": 1,"positions": [0],"offsets": [(0, 13)]},{"doc_id": 2,"term_freq": 1,"positions": [0],"offsets": [(0, 13)]}]},"fast": {"doc_freq": 1,"postings": [{"doc_id": 2,"term_freq": 1,"positions": [2],"offsets": [(17, 21)]}]},"is": {"doc_freq": 2,"postings": [{"doc_id": 1,"term_freq": 1,"positions": [1],"offsets": [(14, 16)]},{"doc_id": 2,"term_freq": 1,"positions": [1],"offsets": [(14, 16)]}]},"powerful": {"doc_freq": 2,"postings": [{"doc_id": 1,"term_freq": 1,"positions": [2],"offsets": [(17, 25)]},{"doc_id": 2,"term_freq": 1,"positions": [4],"offsets": [(27, 35)]}]}} }
-
1.2 倒排索引的构建过程
Elasticsearch 的倒排索引构建过程是其高效搜索能力的核心。以下是倒排索引构建的详细步骤:
-
文档接收与解析:
- Elasticsearch 接收文档(通常为 JSON 格式),并解析文档中的字段。
- 每个文档会被分配一个唯一的文档 ID(_id),用于标识该文档。
-
文本分析与分词:
- 对文档中的文本字段进行分析,生成标准化的词项(Terms)。
- 分析过程包括以下步骤:
- 字符过滤:去除无用字符(如 HTML 标签)。
- 分词(Tokenization):将文本拆分为单独的单词或词条。
- 标准化(Normalization):
- 小写转换(Lowercasing)。
- 去除停用词(Stop Words Removal)。
- 词干提取(Stemming)。
- 生成词项:最终生成一组标准化的词项。
-
构建倒排索引:
- 倒排索引的核心是将词项与文档 ID 建立映射关系。
- 构建过程包括以下步骤:
- 词项与文档映射:
- 对每个词项,记录包含该词项的文档 ID。
- 倒排列表(Posting List):
- 为每个词项创建一个倒排列表,包含以下信息:
- 文档 ID:标识包含该词项的文档。
- 词频(Term Frequency):词项在文档中出现的次数。
- 位置信息(Positions):词项在文档中的具体位置(用于短语查询或高亮显示)。
- 偏移量(Offsets):词项在文档中的起始和结束位置(可选)。
- 为每个词项创建一个倒排列表,包含以下信息:
- 词典(Term Dictionary):
- 将所有词项按字典序排序,并存储到词典中,方便快速查找。
- 词项与文档映射:
-
索引段(Segment)的生成
- Elasticsearch 的索引由多个不可变的段(Segment)组成。
- 构建过程包括以下步骤:
- 内存中的索引:
- 新写入的文档会先在内存中构建倒排索引。
- 刷新(Refresh):
- 每隔一段时间(默认 1 秒),内存中的索引会被刷新到磁盘,生成一个新的索引段。
- 段文件:
- 每个段包含一个完整的倒排索引,以及词典、倒排列表等信息。
- 内存中的索引:
-
段的合并(Segment Merging)
- 随着文档的不断写入,段的数量会逐渐增加,影响查询性能。
- Elasticsearch 会定期执行段合并:
- 选择小段:选择多个小段进行合并。
- 合并索引:将小段的倒排索引合并为更大的段。
- 删除文档清理:在合并过程中,标记为删除的文档会被物理删除,释放存储空间。
-
索引存储与压缩
- 倒排索引以高效的文件格式存储,并使用压缩技术减少存储空间。
- 存储与压缩包括以下内容:
- 词典存储:
- 使用 FST(Finite State Transducer)等数据结构存储词典,支持快速查找。
- 倒排列表存储:
- 使用 FOR(Frame of Reference)、RLE(Run-Length Encoding)等压缩算法存储倒排列表。
- 位置信息存储:
- 使用差值编码(Delta Encoding)等技术压缩位置信息。
- 词典存储:
-
分布式环境下的索引构建
- Elasticsearch 是分布式系统,索引构建过程涉及分片和副本:
- 分片(Sharding):
- 索引被分成多个分片,分布在不同节点上,每个分片是一个独立的倒排索引。
- 副本(Replication):
- 每个分片可以有多个副本,提高可用性和查询性能。
- 分布式写入:
- 文档写入时,会根据路由规则(如 _id 哈希)分配到对应的分片。
- 一致性保证:
- Elasticsearch 使用主从复制机制,确保数据一致性。
- 分片(Sharding):
- Elasticsearch 是分布式系统,索引构建过程涉及分片和副本:
1.3 倒排索引的优势
倒排索引的主要优势在于:
- 高效的全文搜索:
- 快速定位文档:通过词项(Term)快速找到包含该词项的所有文档。
- 支持布尔查询:支持 AND、OR、NOT 等逻辑操作,便于构建复杂的查询条件。
- 示例:
- 在下面这个例子中,Elasticsearch 会从倒排索引中查找 “fast” 对应的文档 ID 列表,并返回相关文档。
GET /my_index/_search {"query": {"match": {"content": "fast"}} }
- 支持短语查询:
- 精确匹配短语:可以查找包含特定短语的文档。
- 支持位置查询:支持基于词项位置的查询(如邻近查询)。
- 示例:
- 在下面这个例子中,Elasticsearch 会查找 “is” 和 “fast” 在文档中相邻的位置,并返回匹配的文档。
GET /my_index/_search {"query": {"match_phrase": {"content": "is fast"}} }
- 支持相关性评分:
- TF-IDF 评分:基于词频和文档频率计算文档的相关性。
- BM25 评分:更先进的评分算法,适用于现代搜索引擎。
- 示例:
- 在下面这个例子中,Elasticsearch 会计算每个文档的相关性评分,并返回最相关的文档。
GET /my_index/_search {"query": {"match": {"content": "elasticsearch"}} }
- 支持多字段搜索
- 跨字段查询:可以在多个字段中搜索同一个词项。
- 字段优先级:可以为不同字段设置不同的权重,影响相关性评分。
- 示例:
- 在下面这个例子中,Elasticsearch 会在 title 和 content 字段中搜索 “fast”,并返回匹配的文档。
GET /my_index/_search {"query": {"multi_match": {"query": "fast","fields": ["title", "content"]}} }
- 高效的布尔查询
- AND 查询:查找同时包含多个词项的文档。
- OR 查询:查找包含任意一个词项的文档。
- NOT 查询:排除包含特定词项的文档。
- 示例:
- 在下面这个例子中,Elasticsearch 会查找同时包含 “fast” 和 “powerful” 的文档。
GET /my_index/_search {"query": {"bool": {"must": [{ "match": { "content": "fast" } },{ "match": { "content": "powerful" } }]}} }
- 支持前缀和通配符查询
- 前缀查询:查找以特定前缀开头的词项。
- 通配符查询:查找符合特定模式的词项。
- 示例:
- 在下面这个例子中,Elasticsearch 会查找以 “elast” 开头的词项(如 “elasticsearch”)。
GET /my_index/_search {"query": {"wildcard": {"content": "elast*"}} }
- 支持模糊查询
- 容错搜索:支持查找与目标词项相似的词项。
- 编辑距离:可以指定允许的最大编辑距离。
- 示例:
- 在下面这个例子中,Elasticsearch 会查找与 “elastik” 相似的词项(如 “elasticsearch”)。
GET /my_index/_search {"query": {"fuzzy": {"content": "elastik"}} }
- 高效的压缩存储
- 差值编码(Delta Encoding):对有序的文档 ID 列表进行压缩。
- FOR(Frame of Reference):对数值型文档 ID 列表进行压缩。
- RBM(Roaring Bitmaps):对稀疏文档 ID 列表进行压缩。
- 支持动态更新
- 实时搜索:新文档可以快速被索引并支持搜索。
- 增量更新:只更新受影响的倒排列表,减少更新开销。
1.4 倒排索引的局限性
尽管倒排索引非常强大,但它也有一些局限性:
- 存储开销:
- 词项存储:倒排索引需要存储所有文档中的词项及其对应的文档列表,词项数量庞大时,存储开销较大。
- 位置信息:为支持短语查询,还需存储词项在文档中的位置信息,进一步增加存储需求。
- 更新开销:
- 实时性差:倒排索引的更新需要重建部分索引,频繁更新会影响性能。
- 删除操作复杂:删除文档时,标记删除而非立即移除,可能导致索引膨胀,需定期合并段(segment merging)来清理。
- 查询性能
- 长尾词项:某些词项出现在大量文档中,查询这些词项时性能较差。
- 复杂查询:布尔查询、短语查询等复杂操作需要合并多个词项的倒排列表,计算量大,性能下降。
- 内存消耗
- 缓存需求:为提升查询性能,常将部分倒排索引缓存到内存,词项多时内存消耗大。
- 堆内存压力:Elasticsearch 依赖 JVM 堆内存,大规模数据时可能引发 GC 问题,影响性能。
- 不适合数值范围查询:
- 倒排索引主要用于文本搜索,对于数值范围查询(如 age > 30),Elasticsearch 使用 BKD Tree 等其他数据结构。
- 文本分析的局限性
- 分词依赖:倒排索引依赖分词器,分词效果直接影响查询准确性,不同语言和领域的分词效果可能不理想。
- 同义词与语义理解:难以处理同义词和语义理解,需额外配置同义词词典或使用 NLP 技术。
1.5 倒排索引的用途
倒排索引主要用于以下场景:
- 全文搜索
- 支持对文本字段的高效全文搜索,通过词项(Term)快速定位包含该词项的文档。
- 例如,搜索 “fast” 时,Elasticsearch 会查找倒排索引中 “fast” 对应的文档 ID 列表。
- 短语查询
- 支持搜索包含特定短语的文档,倒排索引中存储了词项的位置信息(Positions),可以精确匹配短语中词项的顺序和位置。
- 例如,搜索 “Elasticsearch is” 时,可以找到文档中连续出现这两个词项的位置。
- 近似查询
- 支持搜索词项之间距离在一定范围内的文档,利用倒排索引中的位置信息,计算词项之间的距离。
- 例如,搜索 “Elasticsearch” 和 “powerful” 之间距离不超过 5 个词的文档。
- 高亮显示
- 在搜索结果中高亮显示匹配的词项,倒排索引中存储了词项的偏移量(Offsets),可以精确定位词项在文档中的起始和结束位置。
- 根据偏移量提取匹配的词项并进行高亮显示。
- 相关性评分
- 根据文档与查询的相关性对搜索结果进行排序,倒排索引中存储了词频(Term Frequency, TF)和文档频率(Document Frequency, DF)。
- 使用 TF-IDF 或 BM25 等算法计算文档的相关性评分。
- 评分越高,文档与查询的相关性越强。
- 聚合分析
- 支持对搜索结果进行统计分析,倒排索引中存储了词项的文档频率(DF),可以快速计算词项的全局统计信息。
- 例如,计算某个词项在所有文档中出现的频率。
- 自动补全
- 支持搜索时的自动补全功能,倒排索引的词典(Term Dictionary)支持前缀查找,可以快速匹配用户输入的部分词项。
- 例如,输入 “elas” 时,可以自动补全为 “Elasticsearch”。
- 过滤
- 支持对搜索结果进行过滤,倒排索引可以快速判断某个词项是否存在于文档中。
- 例如,过滤出包含 “powerful” 但不包含 “slow” 的文档。
- 排序
- 支持对搜索结果按指定字段排序,倒排索引可以快速访问文档的元数据(如文档 ID、词频等),用于排序。
- 例如,按文档的创建时间或评分进行排序。
1.6 倒排索引的优化
Elasticsearch 在倒排索引的设计和实现中进行了多种优化,以提高存储效率、查询性能和扩展性。以下是 Elasticsearch 对倒排索引的主要优化措施:
-
压缩技术
- 目的:减少存储空间,提高内存和磁盘的利用率。
- 具体优化:
- 文档 ID 压缩:使用 差值编码(Delta Encoding) 对文档 ID 进行压缩。
- 位置信息压缩:使用差值编码对词项的位置信息进行压缩。
- 倒排列表压缩:使用 FOR(Frame of Reference) 和 RLE(Run-Length Encoding) 等算法压缩倒排列表。
- 词典压缩:使用 FST(Finite State Transducer) 压缩词典,支持高效的前缀查找和范围查询。
-
索引段(Segment)管理
- 目的:提高写入性能和查询效率。
- 具体优化:
- 分段存储:索引由多个不可变的段(Segment)组成,每个段是一个独立的倒排索引。
- 近实时刷新:新写入的文档会先在内存中构建倒排索引,然后定期刷新到磁盘生成新的段。
- 段合并:定期将多个小段合并为更大的段,减少段的数量,提升查询性能。
- 删除文档清理:在段合并过程中,标记为删除的文档会被物理删除,释放存储空间。
-
缓存机制
- 目的:加速查询性能。
- 具体优化:
- 过滤器缓存(Filter Cache):缓存常用的过滤查询结果,减少重复计算。
- 字段数据缓存(Field Data Cache):缓存字段的倒排索引数据,加速聚合和排序操作。
- 查询结果缓存(Query Cache):缓存查询结果,适用于重复查询。
- 分片查询缓存(Shard Query Cache):缓存分片级别的查询结果。
-
分布式架构
- 目的:支持大规模数据和高并发查询。
- 具体优化:
- 分片(Sharding):将索引分成多个分片,分布在不同节点上,每个分片是一个独立的倒排索引。
- 副本(Replication):每个分片可以有多个副本,提高可用性和查询性能。
- 分布式查询:查询时,协调节点将请求分发到相关分片,合并结果后返回给客户端。
-
高效的查询执行
- 目的:加速复杂查询的执行。
- 具体优化:
- 跳过不匹配的文档:利用倒排列表的压缩和分块存储,快速跳过不匹配的文档。
- 布尔查询优化:对布尔查询(AND、OR、NOT)进行优化,减少不必要的计算。
- 短语查询优化:利用位置信息快速匹配短语。
-
近实时搜索
- 目的:支持近实时的数据搜索。
- 具体优化:
- 内存索引:新写入的文档会先在内存中构建倒排索引。
- 定期刷新:每隔一段时间(默认 1 秒),内存中的索引会被刷新到磁盘,生成新的段。
- 可搜索性:刷新后,新文档可以立即被搜索到。
-
动态更新与删除
- 目的:支持高效的文档更新和删除。
- 具体优化:
- 标记删除:删除文档时,不会立即从倒排索引中移除,而是标记为删除。
- 段合并清理:在段合并过程中,标记为删除的文档会被物理删除。
- 更新操作:更新文档时,会生成新版本的文档,旧版本的文档会被标记为删除。
-
字段数据类型的优化
- 目的:针对不同数据类型优化存储和查询。
- 具体优化:
- 文本字段:使用倒排索引支持全文搜索。
- 数值字段:使用 BKD Tree 等数据结构支持范围查询和排序。
- 地理位置字段:使用 GeoHash 或 Quadtree 支持地理位置查询。
二、正排索引
在 Elasticsearch 中,正排索引(Forward Index) 也称为 行式存储(Row-based Storage) 或 文档存储(Document Store),用于存储完整的文档内容,以便在搜索完成后快速返回文档的原始数据。与倒排索引(Inverted Index)不同,正排索引的主要作用是快速获取某个文档的内容,而不是查找包含某个词项的文档。正排索引的结构与倒排索引(Inverted Index)相辅相成,共同支持 Elasticsearch 的高效搜索和检索功能。
2.1 正排索引的结构
正排索引的结构可以理解为以文档为中心的存储方式,每个文档的所有字段值存储在一起。以下是正排索引的主要组成部分:
- 文档 ID(DocID)
- 作用:唯一标识一个文档。
- 特点:
- 文档 ID 是正排索引的主键,用于快速定位文档。
- 文档 ID 与倒排索引中的文档 ID 一致。
- 字段值(Field Values)
- 作用:存储文档中每个字段的原始值。
- 特点:
- 字段值按字段名存储,支持快速访问。
- 字段值可以是文本、数值、日期、布尔值、数组等类型。
- Doc Values
- 作用:为字段提供列式存储,用于高效支持聚合、排序和脚本计算。
- 特点:
- Doc Values 是正排索引的一部分,存储字段值的列式数据。
- 默认情况下,所有支持聚合和排序的字段都会启用 Doc Values。
示例:
-
文档内容
- 文档 1:
{"title": "Elasticsearch Guide","author": "John Doe","year": 2023,"tags": ["search", "database"] }
- 文档 2:
{"title": "Introduction to Elasticsearch","author": "Jane Smith","year": 2022,"tags": ["tutorial", "search"] }
- 文档 1:
-
正排索引结构
-
文档 ID(DocID)
- 每个文档有一个唯一的文档 ID,用于标识文档。
-
字段值(Field Values)
- 每个文档的所有字段值按字段名存储。
-
完整正排索引
文档 ID(DocID) 字段名 字段值 1 title “Elasticsearch Guide” 1 author “John Doe” 1 year 2023 1 tags [“search”, “database”] 2 title “Introduction to Elasticsearch” 2 author “Jane Smith” 2 year 2022 2 tags [“tutorial”, “search”] -
Doc Values 结构
Doc Values 是正排索引的一部分,用于支持聚合、排序和脚本计算。以下是 year 和 tags 字段的 Doc Values 结构:-
year 字段的 Doc Values
文档 ID(DocID) year 1 2023 2 2023 -
tags 字段的 Doc Values
文档 ID(DocID) Tag 1 “search” 1 “database” 2 “tutorial” 2 “search”
-
-
存储优化
- 压缩:字段值可以使用压缩算法(如 LZ4)减少存储空间。
- 列式存储:Doc Values 使用列式存储,优化聚合和排序性能。
-
正排索引的 JSON 表示
{"documents": [{"doc_id": 1,"fields": {"title": "Elasticsearch Guide","author": "John Doe","year": 2023,"tags": ["search", "database"]}},{"doc_id": 2,"fields": {"title": "Introduction to Elasticsearch","author": "Jane Smith","year": 2022,"tags": ["tutorial", "search"]}}],"doc_values": {"year": [{"doc_id": 1, "value": 2023},{"doc_id": 2, "value": 2022}],"tags": [{"doc_id": 1, "value": "search"},{"doc_id": 1, "value": "database"},{"doc_id": 2, "value": "tutorial"},{"doc_id": 2, "value": "search"}]} }
-
2.2 正排索引的构建过程
- 文档接收与解析
- 输入文档:Elasticsearch 接收文档(通常为 JSON 格式),并解析文档中的字段。
- 文档 ID:为每个文档分配一个唯一的文档 ID(_id),用于标识该文档。
- 字段提取与存储
- 字段提取:从文档中提取所有字段及其值。
- 字段类型:根据字段的映射(Mapping)确定字段的类型(如文本、数值、日期等)。
- 存储格式:
- 正排索引以行为单位存储文档的所有字段值。
- 对于支持聚合和排序的字段,Elasticsearch 会额外生成 Doc Values(列式存储)。
- 正排索引的构建
- 行式存储:
- 每个文档的所有字段值存储在一起,形成一行数据。
- 例如,文档 1 的正排索引行:
{"title": "Elasticsearch Guide","author": "John Doe","year": 2023,"tags": ["search", "database"] }
- 列式存储(Doc Values):
- 对于需要支持聚合、排序和脚本计算的字段,Elasticsearch 会生成 Doc Values。
- Doc Values 以列为单位存储字段值,例如:
- year 字段的 Doc Values:
文档 ID(DocID) year 1 2023 2 2023 - tags 字段的 Doc Values:
文档 ID(DocID) Tag 1 “search” 1 “database” 2 “tutorial” 2 “search”
- year 字段的 Doc Values:
- 行式存储:
- 存储优化
- 压缩:正排索引中的字段值可以使用压缩算法(如 LZ4)减少存储空间。
- 延迟加载:正排索引的内容可以按需加载,减少内存占用。
- 索引段(Segment)的生成
- 内存中的正排索引:新写入的文档会先在内存中构建正排索引。
- 刷新(Refresh):每隔一段时间(默认 1 秒),内存中的索引会被刷新到磁盘,生成一个新的索引段(Segment)。
- 段文件:每个段包含完整的正排索引和 Doc Values。
- 段的合并(Segment Merging)
- 后台合并:Elasticsearch 会定期将多个小段合并为更大的段,以减少段的数量,提升查询性能。
- 删除文档清理:在合并过程中,标记为删除的文档会被物理删除,释放存储空间。
- 分布式环境下的正排索引
- 分片(Sharding):索引被分成多个分片,分布在不同节点上,每个分片是一个独立的正排索引。
- 副本(Replication):每个分片可以有多个副本,用于提高可用性和查询性能。
- 分布式写入:文档写入时,会根据路由规则(如 _id 哈希)分配到对应的分片。
2.3 正排索引的优势
正排索引的主要优势在于:
- 高效文档内容检索:
- 快速访问文档内容:通过文档 ID 可以直接获取文档的字段值,而不需要遍历倒排索引。
- 适合文档展示:在搜索结果中显示文档的标题、摘要或其他字段时,正排索引能够提供高效的访问性能。
- 示例:
- 在下面这个例子中,Elasticsearch 会从正排索引中快速获取 title 和 content 字段的值。
GET /my_index/_search {"query": {"match": {"title": "Elasticsearch"}},"stored_fields": ["title", "content"] }
- 高效的聚合分析:
- 列式存储:Doc Values 将字段值按列存储,便于高效计算聚合结果(如求和、平均值、唯一值数量等)。
- 支持复杂聚合:正排索引支持嵌套聚合、多字段聚合等复杂操作。
- 示例:
- 在下面这个例子中,Elasticsearch 会从 Doc Values 中获取 age 字段的值,并计算平均值。
GET /my_index/_search {"size": 0,"aggs": {"avg_age": {"avg": {"field": "age"}}} }
- 支持排序:
- 快速排序:通过 Doc Values 可以快速访问字段值,并对文档进行排序。
- 支持多字段排序:正排索引支持基于多个字段的排序操作。
- 示例:
- 在下面这个例子中,Elasticsearch 会从 Doc Values 中获取 age 和 name 字段的值,并对文档进行排序。
GET /my_index/_search {"query": {"match_all": {}},"sort": [{ "age": "asc" },{ "name": "desc" }] }
- 支持脚本计算
- 快速访问字段值:脚本可以直接从 Doc Values 中获取字段值,而不需要加载整个文档。
- 支持复杂计算:脚本可以基于字段值进行计算,并返回自定义结果。
- 示例:
- 在下面这个例子中,Elasticsearch 会从 Doc Values 中获取 age 字段的值,并计算其两倍。
GET /my_index/_search {"script_fields": {"double_age": {"script": {"source": "doc['age'].value * 2"}}} }
- 高亮显示
- 快速获取字段值:正排索引可以快速获取文档的原始内容,用于高亮显示匹配的词项。
- 支持多字段高亮:正排索引支持对多个字段进行高亮显示。
- 示例:
- 在下面这个例子中,Elasticsearch 会从正排索引中获取 content 字段的值,并高亮显示匹配的词项 “fast”。
GET /my_index/_search {"query": {"match": {"content": "fast"}},"highlight": {"fields": {"content": {}}} }
- 存储效率
- 列式存储:Doc Values 将字段值按列存储,便于压缩和高效访问。
- 支持压缩:Doc Values 支持多种压缩算法(如 LZ4、DEFLATE),减少存储空间。
- 适合数值和关键字字段
- 高效访问:数值和关键字字段的值可以直接从 Doc Values 中获取,而不需要分词或倒排索引。
- 支持范围查询:正排索引支持高效的数值范围查询(如 age > 30)。
- 示例:
- 在下面这个例子中,Elasticsearch 会从 Doc Values 中获取 age 字段的值,并查找大于等于 30 的文档。
GET /my_index/_search {"query": {"range": {"age": {"gte": 30}}} }
2.4 正排索引的局限性
尽管正排索引非常有用,但它也有一些局限性:
- 存储开销:
- 完整文档存储:正排索引存储了文档的所有字段值,对于包含大量字段或大字段(如长文本)的文档,存储开销较大。
- 冗余存储:如果文档中有大量重复的字段值(如枚举类型的字段),正排索引会重复存储这些值,导致存储空间浪费。
- 内存占用:
- 字段数据缓存:正排索引中的字段值(尤其是文本字段)需要加载到内存中以支持快速检索,这可能导致内存占用过高。
- 堆内存压力:Elasticsearch 依赖 JVM 堆内存,正排索引的字段数据缓存可能占用大量堆内存,增加垃圾回收(GC)的压力。
- 不适合全文搜索:
- 文本字段检索效率低:正排索引存储的是字段的原始值,无法直接支持高效的全文搜索(如模糊查询、短语查询等)。
- 更新开销
- 文档更新效率低:正排索引以文档为单位存储字段值,更新文档时需要重新写入整个文档,效率较低。
- 段合并开销:更新操作会生成新的段,旧段会被标记为删除,定期合并段会增加系统开销。
- 不适合高基数字段
- 高基数字段:对于高基数(Cardinality)字段(如用户 ID、IP 地址等),正排索引的存储和检索效率较低。
- Doc Values 限制:虽然 Doc Values 支持高基数字段的聚合和排序,但其存储和计算开销仍然较大。
- 字段类型限制
- 不支持嵌套对象的高效存储:正排索引对嵌套对象(Nested Objects)的支持有限,嵌套对象的存储和检索效率较低。
- 大字段性能问题:对于大字段(如长文本、二进制数据),正排索引的存储和检索性能较差。
- 分布式环境下的局限性
- 分片管理:正排索引分布在多个分片上,查询时需要从多个分片获取字段值,增加了网络开销和延迟。
- 副本同步:正排索引的副本需要与主分片保持同步,增加了写入开销。
- 不适合实时分析
- 实时计算性能不足:正排索引主要用于存储和检索字段值,对于实时分析(如复杂聚合、机器学习特征提取)的支持有限。
- 字段数据加载延迟
- 延迟加载:正排索引的字段数据通常是按需加载的,首次访问字段时可能会有延迟。
- 冷数据性能问题:对于不常访问的字段,正排索引的性能可能较差。
- 存储格式的局限性
- 行式存储的局限性:正排索引采用行式存储,对于需要频繁访问某些字段的场景(如聚合分析),效率不如列式存储。
- 压缩效率有限:虽然正排索引支持压缩,但对于某些字段类型(如稀疏字段),压缩效率较低。
2.5 正排索引的用途
正排索引主要用于以下场景:
- 文档内容展示:
- 根据文档 ID 快速获取文档的原始内容。
- 例如,在搜索结果中显示文档的标题和摘要。
- 支持字段检索:
- 在搜索完成后,正排索引用于快速返回文档的特定字段值。
- 例如,搜索完成后,返回文档的 title 和 author 字段。
- 支持聚合分析
- 正排索引中的字段值用于支持聚合操作,如统计、分组、计算等。
- 例如,对 year 字段进行聚合,统计每年的文档数量。
- 支持排序
- 正排索引中的字段值用于对搜索结果进行排序。
- 例如,按 year 字段对搜索结果进行降序排序。
- 支持脚本计算:
- 正排索引中的字段值可以在脚本中使用,用于自定义评分或计算。
- 例如,使用脚本计算文档的评分。
- 支持高亮显示:
- 正排索引中的字段值用于高亮显示搜索结果中的匹配词项。
- 例如,高亮显示 title 字段中的匹配词项。
- 支持字段值过滤:
- 正排索引中的字段值用于过滤搜索结果。
- 例如,过滤出 year 字段值为 2023 的文档。
- 支持嵌套对象:
- 正排索引可以存储嵌套对象的字段值,支持对嵌套对象的检索和聚合。
- 支持多字段检索:
- 正排索引可以存储多个字段的值,支持同时检索多个字段。
- 例如,同时检索 title 和 author 字段。
2.6 正排索引的优化
为了提高正排索引的性能和效率,Elasticsearch 采用了多种优化技术。以下是正排索引的主要优化措施:
- Doc Values 列式存储
- 优化目标:提高聚合、排序和脚本计算的性能。
- 实现方式:
- 将字段值按列存储,而不是按行存储。
- 列式存储更适合批量读取和计算,减少 I/O 开销。
- 适用场景:
- 数值字段、日期字段、关键字字段等。
- 字段数据缓存(Field Data Cache)
- 优化目标:加速字段数据的访问。
- 实现方式:
- 将正排索引中的字段值缓存到内存中,减少磁盘 I/O。
- 适用于频繁访问的字段。
- 注意事项:
- 对于高基数字段(如文本字段),缓存可能占用大量内存。
- 压缩技术
- 优化目标:减少存储空间,提高 I/O 性能。
- 实现方式:
- 使用高效的压缩算法(如 LZ4)压缩字段值。
- 对于稀疏字段(如枚举类型字段),使用差值编码(Delta Encoding)减少存储空间。
- 适用场景:
- 文本字段、数值字段、日期字段等。
- 延迟加载(Lazy Loading)
- 优化目标:减少内存占用,提高资源利用率。
- 实现方式:
- 正排索引的字段值按需加载,而不是一次性加载到内存中。
- 对于不常访问的字段,延迟加载可以减少内存占用。
- 适用场景:
- 大字段(如长文本)、冷数据字段。
三、倒排索引 和 正排索引的区别
在 Elasticsearch 中,倒排索引(Inverted Index) 和 正排索引(Forward Index) 是两种不同的数据结构,分别用于支持不同的搜索和检索功能。以下是它们的核心区别:
- 定义与用途
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 定义 存储词项到文档的映射关系,用于快速定位包含某个词项的文档。 存储文档到字段值的映射关系,用于快速返回文档的原始内容。 主要用途 支持全文搜索、短语查询、模糊查询等。 支持字段检索、聚合分析、排序、脚本计算等。 - 数据结构
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 存储方式 词项到文档的映射(Term → Document)。 文档到字段值的映射(Document → Field Values)。 核心组成部分 -词典(Term Dictionary)
-倒排列表(Posting List)- 文档 ID(DocID)
- 字段值(Field Values) - 存储内容
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 存储内容 - 词项(Term)
- 文档 ID(DocID)
- 词频(TF)
- 位置信息(Positions)
- 偏移量(Offsets)- 文档 ID(DocID)
- 字段值(Field Values) - 查询方式
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 查询方式 通过词项查找包含该词项的文档。 通过文档 ID 查找文档的字段值。 - 适用场景
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 适用场景 - 全文搜索
- 短语查询
- 模糊查询
- 高亮显示- 字段检索
- 聚合分析
- 排序
- 脚本计算 - 性能优化
特性 倒排索引(Inverted Index) 正排索引(Forward Index) 优化技术 - 压缩技术(如 FST、FOR、RLE)
- 缓存机制
- 段合并- Doc Values 列式存储
- 字段数据缓存
- 压缩技术
相关文章:
Elasticsearch 倒排索引 和 正排索引
一、倒排索引 倒排索引是 Elasticsearch 实现高效全文搜索的核心技术。它通过将词项与文档 ID 关联,支持快速检索、短语查询、布尔查询和相关性评分。尽管倒排索引在存储和更新方面有一定的开销,但通过词典优化、倒排列表压缩、分片和缓存等技术&#x…...
Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建
引擎:3.8.5 您好,我是鹤九日! 回顾 前面的几篇文章,讲述的主要是Cocos引擎对Shader使用的一些固定规则,这里汇总下: 一、Shader实现基础是OpenGL ES可编程渲染管线,开发者只需关注顶点着色器和…...
【Python】pillow库学习笔记1-Image类
《Python语言程序设计基础 》第3版,嵩天 黄天羽 杨雅婷著,P293 1.pillow库概述 Pillow 库是Python图像处理重要的第三方库。 Pillow库是PIL (Python image library) 库的一个扩展,需要通过pip工具安装。安装PIL库需要注意,安装…...
解决 MySQL 的 sql_mode 中包含 only_full_group_by模式导致group by SQL报错
sql 报错: Cause: java.sql.SQLSyntaxErrorException: Expression #6 of SELECT list is not in GROUP BY clause and contains nonaggregated column ev_data_transmission.p.push_type which is not functionally dependent on columns in GROUP BY clause; this…...
【微服务架构】本地负载均衡的实现(基于随机算法)
前言 负载均衡 概念:一种将网络流量或业务请求均匀分配到多个服务器或服务实例上的技术,旨在提高系统的可用性、性能和可伸缩性。作用: 提高性能:通过将请求分散到多个实例上,避免单个实例因请求过多而过载ÿ…...
记一次线上SQL死锁事故
一、 引言 SQL死锁是一个常见且复杂的并发控制问题。当多个事务在数据库中互相等待对方释放锁时,就会形成死锁,从而导致事务无法继续执行,影响系统的性能和可用性。死锁不仅会导致数据库操作的阻塞,增加延迟,还可能对…...
电机控制常见面试问题(十八)
文章目录 一.电机控制高级拓扑结构1.LLC 二.谈谈电压器饱和后果三.电压器绕组连接方式的影响四.有源逆变的条件 一.电机控制高级拓扑结构 1.LLC LLC是什么?—— 一个会"变魔术"的电源盒子 想象你有一个魔法盒子,能把电池的电压变大或变小&…...
数据结构之双链表
目录 1 简介 2 双链表的基本概念 2.1 节点结构 2.2 头插法和尾插法 3 代码实现 4 代码解析(部分) 4.1 初始化双链表 4.2 添加节点 4.3 删除节点 4.4 获取节点 4.5 插入节点 4.6 反转链表 4.7 打印链表 4.8 核心操作分析 5 总结 1 简介 …...
dell 台式机 电脑 纽扣电池 如何取下?
dell 台式机 电脑 纽扣电池 如何取下? 戴尔-optiplex-3060-塔式机-服务手册...
JSON二次序列化问题分析
正常的JSON应该是: json Apply to VectorServic... { "id": "d471c19c-70eb-4f29-8604-b8284e8a9400", "text": "人为干预, 降低生产成本...", "metadata": { "chunkIndex": 2, …...
WebSocket 传输大量数据好不好?稳定不稳定
使用 WebSocket 传输大量数据 是可行的,但在实际应用中需要注意一些限制和优化策略。以下是关于 WebSocket 传输大量数据的详细分析: 1. WebSocket 传输大量数据的可行性 优点 实时性:WebSocket 是全双工通信协议,适合实时传输数…...
代码随想录刷题day52|(二叉树篇)106.从中序与后序遍历序列构造二叉树(▲
目录 一、二叉树理论知识 二、构造二叉树思路 2.1 构造二叉树流程(给定中序后序 2.2 整体步骤 2.3 递归思路 2.4 给定前序和后序 三、相关算法题目 四、易错点 一、二叉树理论知识 详见:代码随想录刷题day34|(二叉树篇)二…...
无人设备遥控器之调度自动化技术篇
一、技术原理 信息采集与处理: 通过传感器、仪表等设备采集无人设备的各种数据,如位置、速度、状态等。 将采集到的数据传输到调度自动化系统中进行处理和分析,以获取设备的实时状态。 系统建模与优化: 调度自动化系统会根据…...
红宝书第十五讲:详解JavaScript迭代器与生成器:Symbol.iterator与yield
红宝书第十五讲:详解JavaScript迭代器与生成器:Symbol.iterator与yield 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、迭代器(Iterator)的“传送带”模式 迭代…...
【AI】NLP
不定期更新,建议关注收藏点赞。 目录 transformer大语言模型Google Gemma疫情网民情绪识别 整体框架 baseline构建 模型调参、模型优化、其他模型 数据trick、指标优化、magic feature 数据增强、伪标签、迁移学习 模型融合sklearn中TFIDF参数详解 频率阈值可以去掉…...
ENSP学习day10
NAT地址转换技术(一) NAT(Network Address Translation)地址转换技术是一种在计算机网络中常用的技术,在数据包从一个网络传输到另一个网络时,会对数据包中的源IP地址和目的IP地址进行修改的过程。这种技术…...
文件上传绕过的小点总结(4)
9.末尾点删除处理缺陷 给出源码: $file_name trim($_FILES[upload_file][name]); $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_ext strtolower($file_ext); //转换为小写 $file_ext str_ireplace(::$DATA,…...
实战-MySQL5.7升级8.0遇到的四个问题
近期几个项目的MySQL由5.7升级到8.0,升级过程中遇到四个问题,记录下来分享一下: 第一个问题详见之前的文章: MySQL 5.7升级8.0报异常:处理新增关键字 第二个问题详见之前的文章: MySQL 5.7升级8.0报异常…...
卷积神经网络的原理、实现及变体
卷积神经网络convolutional neural network,CNN 是为处理图像数据而生的网络,主要由卷积层(填充和步幅)、池化层(汇聚层)、全连接层组成。 卷积 虽然卷积层得名于卷积(convolution)…...
java 线程创建Executors 和 ThreadPoolExecutor 和 CompletableFuture 三者 区别
Executors是一个线程池的工具类,而ThreadPoolExecutor是Executor接口的一个实现,是线程池的核心类。 Executors提供了多种快速创建线程池的方法,而ThreadPoolExecutor则提供了更高的自定义和控制能力。 Executors是一个工具类࿰…...
Redisson 实现分布式锁简单解析
目录 Redisson 实现分布式锁业务方法:加锁逻辑LockUtil 工具类锁余额方法:工具类代码枚举代码 RedisUtil 工具类tryLock 方法及重载【分布式锁具体实现】Supplier 函数式接口调用分析 Redisson 实现分布式锁 业务方法: 如图,简单…...
Python条件处理,新手入门到精通
Python条件处理,新手入门到精通 对话实录 **小白**:(崩溃)我写了if x 1:,为什么Python会报错? **专家**:(推眼镜)**是赋值,才是比较**!想判断相…...
详细比较StringRedisTemplate和RedisTemplate的区别及使用方法,及解决融合使用方法
前言 感觉StringRedisTemplate和RedisTemplate非常的相识,到底有什么区别和联系呢?点开idea,打开其依赖关系,可以看出只需使用maven依赖包spring-boot-starter-data-redis,然后在service中注入StringRedisTemplate或者…...
开源模型应用落地-语音转文本-whisper模型-AIGC应用探索(五)
一、前言 在上一节中,学习了如何使用vLLM来部署Whisper-large-v3-turbo模型。不过,在实际使用时,模型一次只能处理30秒的音频。今天,将结合实际业务,介绍如何处理一段完整的音频,并生成相应的字幕文件。 相…...
python每日十题(10)
在Python语言中,源文件的扩展名(后缀名)一般使用.py。 保留字,也称关键字,是指被编程语言内部定义并保留使用的标识符。Python 3.x有35个关键字,分别为:and,as,assert&am…...
安装和部署Tomcat并在idea创建web文件
一、背景 实验任务为安装Tomcat并创建web文件 为提高安装效率并且通俗易懂,免得大量文字浪费时间,这里我们采用图片加文字的方式来给大家讲解这个安装教程。 二、安装过程 首先第一步一定要注意你是否下载了JDK,如果你是像我一样下载一个…...
【Linux】Ubuntu 24.04 LTS 安装 OpenJDK 8
目录 通过 apt-get 直接安装 JDK 1. 更新 apt 软件源 2. 检查 JDK 是否已安装 3. 安装OpenJDK 4. 检查 JDK 是否成功安装 5. 设置 JAVA_HOME 环境变量 找到需要设置的 Java 路径 使用文本编辑器打开/etc/environment文件 添加 Java 安装路径 应用更改和验证配置 通过…...
图灵300题-21~40-笔记002
图灵300题 图灵面试题视频:https://www.bilibili.com/video/BV17z421B7rB?spm_id_from333.788.videopod.episodes&vd_sourcebe7914db0accdc2315623a7ad0709b85&p20。 本文是学习笔记,如果需要面试没有时间阅读原博文,可以快速浏览笔…...
蓝桥杯--bfs专题第二个题目(leetcode103二叉树)
文章目录 1.题目概述2.思路分析3.代码分析 1.题目概述 这个题目是关于二叉树的锯齿形的遍历:这个锯齿形是什么意思呢?简单的通俗的解释,就是S型的,例如下面的这个示例里面的二叉树: 第一行从左到右:但是只…...
React 知识回顾(HOC、合成事件、Fiber)
HOC 嗯,用户问的是HOC是什么以及它能用来做什么。我需要先理解HOC的基本概念,然后整理它的用途。根据搜索结果,HOC是React中的高阶组件,用来复用逻辑。网页1提到HOC是一个函数,接收组件返回新组件,属于设计…...
s1: Simple test-time scaling 【论文阅读笔记】
s1: Simple test-time scaling 关于test-time scaling 这个概念其实是相对 train scaling而言的。train scalling 指的是增加训练数据,增加训练flops等等,投入更多资源在train上。test-time scaling,其实现在简化点的理解,就是 …...
基于 Milvus 和 BiomedBERT 的医学文献智能搜索系统
前言 随着医学研究的不断深入,文献数量呈爆炸式增长,如何快速从海量文献中提取关键信息成为一大挑战。最近,我基于 Milvus 向量数据库和 BiomedBERT 嵌入模型,开发了一个智能搜索系统,支持语义搜索和关键词匹配&#…...
ASP.NET Web的 Razor Pages应用,配置热重载,解决.NET Core MVC 页面在更改后不刷新
Razor Pages应用,修改页面查看修改效果,如果没有热重载,改一句话跑一次,这个活就没法干了。 1、VS2022中的NuGet中安装RuntimeCompilation Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 需要配套你的.net sdk版本&#x…...
MySQL 对text类型字段添加索引
对于 MySQL 中的 text 类型字段,可以通过以下步骤向其添加索引: 创建辅助字段:创建一个辅助字段,将该字段的一部分数据转移到辅助字段中。例如,可以创建一个 varchar 类型的字段来存储 text 字段的前缀。 添加索引&am…...
深入解析SQL2API平台:数据交互革新者
在数字化转型持续深入的当下,企业对数据的高效利用与管理的需求愈发迫切。SQL2API平台应运而生,成为助力企业突破数据交互困境的有力工具,特别是它由麦聪软件基于DaaS(数据即服务)产品创新衍生而来,备受业界…...
@Autowired 和 @Resource 注解的区别
前言 Autowired 和 Resource 是 Spring 中用于依赖注入的注解,但两者在实现机制和使用方式上有显著差异。 主要区别 1.来源不同 Autowired:由 Spring 框架提供(org.springframework.beans.factory.annotation),与 S…...
稳定运行的以ElasticSearch数据库为数据源和目标的ETL性能变差时提高性能方法和步骤
在使用 Elasticsearch 作为数据源和目标的 ETL(Extract, Transform, Load)过程中,性能逐渐变差的原因可能有很多,比如查询效率下降、集群负载过高、资源配置不合理等。 性能的提升通常需要从多个方面入手,尤其是在处理…...
游戏引擎学习第182天
回顾和今天的计划 昨天的进展令人惊喜,原本的调试系统已经被一个新的系统完全替换,新系统不仅能完成原有的所有功能,还能捕获完整的调试信息,包括时间戳等关键数据。这次的替换非常顺利,效果很好。 今天的重点是在此基…...
EJS缓存解决多页面相同闪动问题
基于 EJS 的模板引擎特性及其缓存机制,以下是关于缓存相同模块的详细解答: 一、EJS 缓存机制的核心能力 模板编译缓存 EJS 默认会将编译后的模板函数缓存在内存中,当相同模板文件被多次渲染时,会直接复用已编译的模板函数&#x…...
【MySQL】mysql日志文件
目录 日志文件特征 错误日志(Error log ) 常规查询日志(General query log ) 慢速查询日志(Slow query log ) 审计日志(Audit log ) 二进制日志(Binary log &#…...
【C++】STL性能优化实战
STL性能优化实战 STL (Standard Template Library) 是 C 标准库的核心部分,提供了各种容器、算法和迭代器。虽然 STL 提供了强大的功能,但不恰当的使用可能导致性能问题。下面我将详细介绍 STL 性能优化的实战技巧,并通过具体案例说明。 1.…...
Playwright + MCP:用AI对话重新定义浏览器自动化,效率提升300%!
一、引言:自动化测试的“瓶颈”与MCP的革新 传统自动化测试依赖开发者手动编写脚本,不仅耗时且容易因页面动态变化失效。例如,一个简单的登录流程可能需要开发者手动定位元素、处理等待逻辑,甚至反复调试超时问题。而MCP…...
12-scala样例类(Case Classes)
例类(Case classes)和普通类差不多,只有几点关键差别,接下来的介绍将会涵盖这些差别。样例类非常适合用于不可变的数据。 定义一个样例类 一个最简单的样例类定义由关键字case class,类名,参数列表&#…...
WPF 与 C# 开发深度剖析
一、引言 在当今的软件开发领域,Windows 平台依旧占据着重要的地位。而 WPF(Windows Presentation Foundation)作为微软推出的一款强大的用户界面(UI)框架,为开发者提供了丰富的功能和灵活的设计方式&…...
【工具使用-编译器】VScode(Ubuntu)使用
1. VScode的快捷键 快捷键功能说明Ctrl+Shift+P / F1显示命令面板Ctrl+P快速打开文件Ctrl+Shift+N新建窗口Ctrl+Shift+W关闭窗口Ctrl+,打开设置Ctrl+K Ctrl+S打开快捷键设置Ctrl+X剪切行(无选中时剪切整行)Ctrl+C复制行(无选中时复制整行)Alt+↑ / Alt+↓向上/向下移动行Sh…...
C# SerialPort 使用详解
总目录 前言 在工业控制、物联网、嵌入式开发等领域,串口通信(Serial Port Communication)是连接串行设备(如条码扫描器、GPS接收器等)与计算机的重要手段。C# 提供了内置的 SerialPort 类,简化了串口开发…...
数据结构--二叉排序树
一、二叉排序树的定义 二叉排序树,又称二叉查找树。 性质: 左子树结点值<根结点值<右子树结点值(进行中序遍历,可以得到一个递增的有序序列) 二、查找操作 利用二叉排序树的性质,如果树空,…...
FPGA的直方图均衡
文章目录 一、直方图均衡二、代码实现三、仿真 一、直方图均衡 直方图均衡(Histogram Equalization)是一种用于增强图像对比度的图像处理技术。它通过重新分配图像像素的灰度值,使得图像的灰度直方图在整个灰度范围内均匀分布,从而…...
使用Python将视频转化为gif
使用Python将视频转化为gif 一、前言二、准备三、测试 一、前言 最近想把喜欢的视频片段作成gif,就试着用Python做了下,感觉效果还行,这里做个记录。 二、准备 先下载安装对应的库,命令如下: pip install moviepy …...
基于javaweb的SpringBoot雪具商城系统设计与实现系统(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、…...