#第一性原理 花五到十倍的更大存储空间来换时间 要理解倒排,首先要知道啥是正排,正就是拿着 list,然后 contains 某个词,会非常慢,而倒排就是提前统计好某个词在哪些文档里出现,从而缩小查找范围,加快查找速度。 对于一个包含多个词汇的文档,倒排索引会将每个词汇作为一个关键字(Term),然后记录下该词汇所在的文档编号(Document ID)及该词汇在文档中的位置(Term Position)。这样,当用户输入一个关键字时,就可以快速地查找到包含该关键字的文档编号,然后通过文档编号再查找到对应的文档内容。 # Notes ## 本质 要理解倒排,首先要知道啥是正排,正就是拿着 list,然后 contains 某个词,会非常慢,而倒排就是提前统计好某个词在哪些文档里出现,从而缩小查找范围,加快查找速度。 ### **原始文档(1个文档)** ```json { "title": "北京三日游攻略", "description": "深度游览故宫、长城和颐和园,体验古都文化魅力" } ``` **存储空间**:约 100 字节 ### **倒排索引(分词后)** ```Java "北京" → [文档1:位置0] "三日" → [文档1:位置1] "游" → [文档1:位置2] "攻略" → [文档1:位置3] "深度" → [文档1:位置4] "游览" → [文档1:位置5] "故宫" → [文档1:位置6] "长城" → [文档1:位置7] "和" → [文档1:位置8] "颐和园" → [文档1:位置9] "体验" → [文档1:位置10] "古都" → [文档1:位置11] "文化" → [文档1:位置12] "魅力" → [文档1:位置13] ``` **存储空间**:约 300-500 字节(3-5倍增长) ## 时间与空间 ### 实际存储空间对比 **小规模数据** ```Java 原始文档:1MB 倒排索引:3-5MB 空间增长:3-5倍 ``` **大规模数据** ```Java 原始文档:1GB 倒排索引:5-10GB 空间增长:5-10倍 ``` **超大规模数据** ```Java 原始文档:100GB 倒排索引:500GB-1TB 空间增长:5-10倍 ``` ### 存储空间增长的原因 **1. 词汇重复存储** ```Java 原始文本:"北京三日游攻略" 分词结果:["北京", "三日", "游", "攻略"] 每个词汇都要单独存储,包括: - 词汇本身 - 文档ID - 位置信息 - 频率信息 ``` **2. 位置信息开销** ```Java "故宫" → [文档1:位置6, 文档2:位置12, 文档3:位置8] 每个词汇在每个文档中的位置都需要记录: - 文档ID - 位置编号 - 偏移量 - 长度信息 ``` **3. 元数据开销** ```Java 每个词汇的索引信息包括: - 词汇本身 - 文档频率(DF) - 总词频(TF) - 位置列表 - 偏移量列表 ``` ## 为什么值得这样做? **1. 查询性能提升** ```Java 原始查询:需要扫描所有文档 倒排索引:直接定位到包含关键词的文档 性能提升:从 O(n) 提升到 O(log n) 或 O(1) ``` **2. 用户体验改善** ```Java 搜索响应时间: - 原始方式:秒级 - 倒排索引:毫秒级 提升:100-1000倍 ``` **3. 业务价值** ```Java 电商搜索:快速找到商品 内容搜索:快速找到文章 地理位置:快速找到地点 ``` ## 存储空间优化策略 **1. 压缩技术** ```Java - 词汇压缩:使用字典编码 - 位置压缩:使用增量编码 - 文档ID压缩:使用排序和差值编码 ``` **2. 索引优化** ```Java - 只索引重要字段 - 使用 stop words 过滤 - 设置合理的字段权重 ``` **3. 存储策略** ```Java - 热数据:SSD存储 - 冷数据:HDD存储 - 分层存储:根据访问频率 ```