bleve boltdb性能调研

背景
bleve是go实现的一个简单的文本索引系统。
boltdb是go实现的一个k-v数据库。
bleve使用boltdb作为其存储方式。

问题
在我们的项目中,使用bleve做文档索引,文档长度平均为1w个字节,发现每个文档调用bleve进行index要花费10ms以上。
当文档个数增加至40w,按照10ms的速度,对所有文档进行index需要 4000s 即 1h的时间。
而实际情况下,前面大概1w个文档,每个可以在10ms的时间完成index,而越往后,所需时间越长,直到最终达到40ms。
所以完成40w个文档的index,需要约 2.5 小时。

调研
这个时间无法接受,于是对bleve index耗时进行分析。
进行实验,对1000个长度为X的文档做index,计算平均时间。
当文档长度X在1000字节以内时,速度很快,每个文档的处理在2ms以内。而当文档长度逐渐增加至2w字节,每个文档处理时间就增至12ms。
于是查看bleve index的源码,最终锁定在bolt.Tx.write(),tx.db.ops.writeAt(buf, offset) 实际上是一次 pwrite 系统调用,是一次写磁盘操作。
注意这个调用处于一个循环中,所以有必要看一下循环次数。每次pwrite调用针对的是一个page,而系统的pagesize大多数情况下为4k,所以估算2w个字节需要 10个 page? wrong!
实验表明,文档长度为100字节以内时,pwrite调用次数为5,而当文档长度为2w,pwrite调用次数为 49,这就可以解释为什么随着文档长度增加,做index的耗时会成倍增加。
bleve存在数据库中的并不单单是文档内容本身,它有自己的一层结构,将文档内容放在结构中存入数据库,所以page个数并不是简单的 文档长度/pagesize 。

boltdb性能确实一般
在调研过程中,也看到了一些抱怨boltdb写数据性能的:
https://github.com/boltdb/bolt/issues/237
作者也曾想对此进行优化:
https://github.com/boltdb/bolt/issues/238

TODO
调研别的k-v数据库是如何实现写操作的,是否会比bolt快很多?

你可能感兴趣的:(bleve boltdb性能调研)