Solr的Facet优化

这两周一直奋斗在一个有4亿条(200G)数据的项目当中,需求是需要快速的对数据进行检索和Facet/Group。

搭建了3台Solr服务器(4核8G)做Cloud,分了3个Shard,2个Replication,按道理性能应该不会差,实际跑下来,普通的检索完全没有问题,但是一旦做facet,Solr就要么报java.lang.OutOfMemoryError: Java heap space的错误,要么就是直接进程死掉!

本来想做facet,如果返回的结果数量很大,那么做facet速度慢是正常的,要统计里面出现的唯一数据,要做大量的循环,也消耗内存,但实际上返回结果数量只有十几条,也会报OutOfMemoryError,实在是诡异。

于是求助google,用OutOfMemoryError去搜,没有实质性的结果,通过搜索“solr facet优化”,发现了这样的说明:

当Sorting, faceting时, 通过设置DocValues来保存记录域值的方式是非常高效的。
Solr通过倒排建立索引, 首先建立term list, 然后每个term对应一个document list。 这样

因为传统的Solr建立Index是通过倒排索引建立的Index, 首先建立term list, 然后每个term对应一个document list, 这样的结构使得查询能够非常快速, 因为terms在内存中有已经准备好的term-to-documentList.

对于其它的我们的搜索, 如sorting, faceting, 和highlighting, 倒排索引并不是非常有效。 比如对faceting来讲, 必须先得到在每一个document中的term组装成结果集, 再得到document IDs. 这些所有操作都是在内存中, 当数据量大的时候 , 会使速度减慢, 并且会占用宝贵的内存资源。

在Lucene4.0以后,DocValue 以面向列的存储方式被引用。这是以document-to-value mapping 的方式在index时被创建。 减轻了fieldCache的内存需求, 使faceting, sorting, grouping更加快速。

使用DocValues很简单,修改schema.xml即可。但是有一个限制,text字段是无法设置DocValues属性的。

如果这周末能把4亿条数据导完,检验一下结果吧!