【Golang系统开发】搜索引擎(3) 压缩倒排索引表

写在前面

假设我们的数据集中有 800000 篇文章,每篇文章有 200 词条,每个词条有6个字符,倒排记录数目是 1 亿。那么如果我们倒排索引表中单单记录文档id,不记录文档内的频率和偏移信息。

那么 文档id 的长度就必须是 l o g 2 800000 = 20 b i t log_2800000=20 bit log2800000=20bit (文档可能每篇文章都存在,所以是以最长的长度要求),所以我们整个未压缩的倒排索引表的大小大概有,倒排记录数 * 文档id大小 = 100,000,000 * 20/8 = 250 MB

为了设计出一个更高效的倒排文件的表示方式,可以考虑每篇文档采用少雨20位的表示方法,观察中发现。高频词出现的文档id的序列相差不大。比如高频词 "大学",我们去找一篇包含 大学 的文档,可能我们找了一个之后,不久又找到一个,这些文档id之间的gap(间距)不大,因此可以考虑用比20位端很多的位数来表示它。为了对这种间距分布的情况进行空间压缩,需要使用一种变长编码方法,这种方法可以对短间距采用更短的位数来表示

1. 可变字节码

VB(variable byte,可变字节) 编码利用整数个字节来对间距编码。字节的后7位是间距的有效编码区,而第一位是延续位。如果该位为1,则表明本字节是某个间距编码的最后一个字节,否则不是。要对一个可变字节编码进行解码,可以读入一段字节序列,其中前面的字节的延续位都为0,而最后一个字节的延续位为1。根据上述标识可以把每个字节的7位部分抽取出来并链接在一起形成编码。

go语言实现vb的编码,VBEncodeNumber 将整数编码为VB编码的字符串

go 复制代码
func VBEncodeNumber(n uint32) string {
	var bytes []uint32

	for {
		bytes = append(bytes, n%128+128)
		if n < 128 {
			break
		}
		n = n / 128
	}

	var by []string
	for i := len(bytes) - 1; i >= 0; i-- {
		if i < len(bytes)-1 {
			by = append(by, strconv.FormatUint(uint64(bytes[i]), 2)[1:]+" ")
		} else {
			by = append(by, strconv.FormatUint(uint64(bytes[i]), 2))
		}
	}

	return strings.Join(by, "")
}

通过vb编解码,我们可以实现50%的压缩

相关推荐
caoerzhong2 分钟前
JeeWMS 开源 WMS 部署避坑指南:Java 仓库管理系统的环境基线、四类根因与可复现交付
java·开发语言·开源
时间的拾荒人5 分钟前
Qt 界面优化:绘图详解 —— 从基础图形到图片处理
开发语言·qt·面试
MayZork22 分钟前
Qt 文件操作:QSaveFile 与 QTemporaryFile(含 QTemporaryDir)实战
开发语言·qt
北冥you鱼35 分钟前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
xh didida1 小时前
Linux -- 基础IO
linux·服务器·开发语言·c++
个 人 练 习 生1 小时前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
2601_966949651 小时前
多市场量化策略的数据接口应该如何设计:从数据层架构到策略接入
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
坤坤子吖1 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
奋斗的阿狸_19861 小时前
ESP32-S3 + ES7210 四通道麦克风录音上传方案
c语言·开发语言·fpga开发
weixin199701080162 小时前
《1688图片空间API踩坑:img.upload 与 album.* 的防盗链与CDN缓存问题》(附Python源码)
开发语言·python·缓存