临沂网站seo,免费进销存软件,做网站的windowlcd,wordpress网站vip可看gin全称generalized inverted index#xff0c;即“通用倒排索引”。顾名思义#xff0c;是一种倒排索引#xff0c;但被设计成可以支持多种复杂数据类型的索引需求。
gin索引最初是为了支持全文检索而引入的。在postgresql 8.2版本中首次引入。当时#xff0c;postgresql已…gin全称generalized inverted index即“通用倒排索引”。顾名思义是一种倒排索引但被设计成可以支持多种复杂数据类型的索引需求。gin索引最初是为了支持全文检索而引入的。在postgresql 8.2版本中首次引入。当时postgresql已经内置了全文检索功能但是缺乏高效地索引支持。gin索引的设计初衷就是为全文加你所提供一种高效的索引结构能够快速查找包含特定词汇的文档。随着时间推移gin索引的适用范围被扩展到了其他数据类型例如数组、jsonb范围类型等成为了一个“通用”的倒排索引。倒排索引的倒排到底“倒”在哪里这个“倒”主要指“查询路径的方向”被逆转了。特性正排索引(forward index)倒排索引(inverted index)存储结构文档id——文档内容词1词2词3……词——包含该词的文档id列表类比一本书的目录按章节顺序一本书末尾的索引按关键字字母顺序查询方式知道要哪本书id想查看内容不知道要哪本书只知道像查找的内容关键字核心问题回答“这个文档里由什么”回答“哪些文档里有这个”“倒”就是把“文档—词”这个自然的包含关系你转成了“词—文档”这个为了快速检索而建立的反向映射关系。文档是主要的组织单元是“正”的、顺向的七点。传统的查找正排是沿着document—terms这个正向链接。而倒排索引为了加速搜索创建了term—documents这个方向链接。“倒排索引”的英文是inverted index这里的inverted就是反转的、倒置的意思。它指的就是把索引的键和值给反转了。GIN将这一思想泛化索引的键key不再是简单的列值而是从被索引的复杂值如数组、全文检索的tsvector、jsonb中提取出的所有元素或标记tokens。索引条目就是元素—包含该元素的所有行TID列表。GIN索引的内部结构gin索引是一个两层树结构由两部分组成1、B-tree的元树metapage and b-tree这是一个常规的b-tree结构但它存储的不指数据的指针而是从被索引数据中提取出的唯一“键”key。例如对于一个文本数组{‘cat’,‘dog’,‘fish’},‘cat’,‘dog’,fish’者三个词或它们的哈希值都会作为独立的键插入到这个b-tree中。这个b-tree提供了对键值的快速查找能力。2、倒排列表posting list/posting tree这是gin索引的灵魂。在b-tree的叶子节点中每个“键”后面都挂载着一个posting list或posting tree。posting list一个经过压缩、有序的itempointer即行指针TID列表。它记录了所有包含该键的数据行的位置。例如键’cat’的posting list里存折第1、5、100、200行这些行的数组或文本中包含’cat’。posting tree当一个键出现在非常多的行中时例如一个常见的单词其posting list会变得非常庞大。为了更高效地管理和查找gin会将其转换为一个效地b-tree即posting tree。这本质上将大列表“索引化“加速在大量指针中的查找。索引的构建插入过程当向表中插入一行新数据时假设该表的某列已创建gin索引1、提取键数据库会调用与该列数据类型对应的extractValue函数对于tsvector或extractQuery函数对于其他类型实际是解析函数从该列的之中提取出所有元素/标记。‘the quick brown fox’tsvector——{‘the’,‘quick’,‘brown’,‘fox’}[‘apple’,‘banana’] (array——‘apple’,‘banana’{“a”:1,“b”:2}(JSONB)——“a”,1b,2取决于具体操作符类2、更新索引对于提取出的每个唯一键系统会在顶层的b-tree中查找该键。如果键不存在则插入这个新键并创建一个只包含新行tid的posting list。如果键已存在则将新行的tid添加到该键对应的posting list或posting tree的末尾系统会维护列表的有序性。由于一行数据可能产生多个键插入一行可能会更新索引中的多个条目因此gin索引的构建和更新通常比b-tree慢。查询工作原理这是gin效率的体现。以查询”数据列包含元素’apple‘”column {apple}为例1、解析查询查询本身’{apple}‘也会被同一个extractQuery函数处理提取出要查找的‘apple’。2、查找键在gin顶层的b-tree中快速定位到键‘apple’。3、获取候选行取出‘apple’键后面挂载的整个posting list或遍历posting tree。这个列表里的所有tid都是潜在的候选行因为它们都包含‘apple‘。4、位图扫描与重检查consistency check-关键步骤数据库会收集所有候选行的tid并使用位图堆扫描bitmap heap scan来从表中取出这些候选行的实际数据。为什么需要重检查因为gin是“有损”的。索引只记录了“行包含键”但没有记录键之间的关系比如在数组中的具体位置、出现的次数等。最终的查询条件如,?需要在原始数据上重新计算。数据库将去除的每一行原始数据根据查询条件进行重检查recheck。只有通过重检查的行才会作为最终结果返回。这是gin索引查询计划中常见的一个步骤bitmap heap scan后面跟着一个recheck cond过滤器。对于多键查询如column’apple‘’banana‘数据库会分别找到’apple‘和’banana‘的posting list。然后堆这两个列表取交集因为条件是and。这个交集操作在有序的、压缩的tid列表上进行非常高效。最后对交集得到的tid列表进行位图扫描和重检查。GIN的核心特点与适用场景1、适用场景全文搜索tsvector列上的操作符查询。数组类型(包含)(被包含)(重叠)(存在)等操作符。json/jsonb类型?,?,?|,等操作符。范围类型重叠等操作符。任何可以明确定义“键提取”和一致性检查“函数的数据类型。2、优势多键查询快尤其是and/or条件通过列表的交并集运算高效完成。支持复杂查询为超越等值查询的复杂包含关系提供了高效路径。压缩存储posting list使用压缩空间效率高。3、劣势构建和更新慢一行数据对应索引多个条目写入开销大。有损索引必须进行重检查对于海量数据如果候选集很大如果查询一个非常常见的词重检查可能称为性能瓶颈。精确匹配慢对于arrary_column’{apple,banana}‘这种精确等值查询b-tree通常比gin更快。因为gin需要合并两个键的列表并重检查而b-tree直接定位。总结GIN索引是一个为了“包含性查询”而生的基于倒排索引思想的、两层b-tree posting list /tree的、有损的通用索引。它的工作流程可以概括为提取查询键——在b-tree中定位——获取posting list——合并列表如需要——位图扫描——关键的重检查。