Lucene系列-Fieldcache

FiledCache介绍
Lucene作为列缓存, 可以获取设置了Filed.Store.Yes上的正排数据信息.通常IndexSearcher.doc(docId)获得Document的所有域值,访问速度比较慢.但是通过FieldCache读取doc的分片信息,速度可以提升很多.
注意:FieldCache并非在存储域中读取,而是在索引域中读取,从而不必构造Document对象,要求此索引域是不分词的,有且只有一个Token.

在lucene中,一些用于排序的字段,lucene 在首次使用的时候将这个field下所有term转换成float(如下图所示),并存放入FieldCache中,这样在第二次使用的时候就能直接从该缓存中获取。从term->docId倒排信息转化为常驻内存的正排信息.(数组中index为docid的次序)
Lucene系列-Fieldcache_第1张图片

代码示例:

    DirectoryReader dirReader = (DirectoryReader) DirectoryReader.open(IDX_DIR);;
    FieldCache.Ints ints = FieldCache.DEFAULT.getInts(dirReader.leaves().get(0).reader(), "id", false);
    BinaryDocValues terms = FieldCache.DEFAULT.getTerms(dirReader.leaves().get(0).reader(), "string", false);
    BytesRef bytesRef = terms.get(0);
    Assert.assertEquals("abc", bytesRef.utf8ToString());

从示例代码中可以看出,FieldCache通过FieldCacheImpl来实现缓存的功能,而FiledCacheImpl底层实现是利用 WeakHashMap, 详见代码:

    /** Expert: Internal cache. */
    abstract static class Cache {

      Cache(FieldCacheImpl wrapper) {
        this.wrapper = wrapper;
      }

      final FieldCacheImpl wrapper;

      final Map<Object,Map<CacheKey,Accountable>> readerCache = new WeakHashMap<>();

      protected abstract Accountable createValue(AtomicReader reader, CacheKey key, boolean setDocsWithField)
          throws IOException;

      /** Remove this reader from the cache, if present. */
      public void purgeByCacheKey(Object coreCacheKey) {
        synchronized(readerCache) {
          readerCache.remove(coreCacheKey);
        }
      }

WeakHashMap包含了一个自动调用的方法expungeStaleEntries,这样就会在值被引用后直接执行这个隐含的方法,将不用的键清除掉.

FieldCacheImpl中get函数获取流程
FiledCache在数据获取过程中, 首先到DocValues中获取,如果数据不存在,然后通过FiledCacheImpl读取cache信息.DocValues优点见:Lucene系列-docValues

    public BinaryDocValues getTerms(AtomicReader reader, String field, boolean setDocsWithField, float acceptableOverheadRatio) throws IOException {
    BinaryDocValues valuesIn = reader.getBinaryDocValues(field);
    if (valuesIn == null) {
      valuesIn = reader.getSortedDocValues(field);
    }

    if (valuesIn != null) {
      // Not cached here by FieldCacheImpl (cached instead
      // per-thread by SegmentReader):
      return valuesIn;
    }

    final FieldInfo info = reader.getFieldInfos().fieldInfo(field);
    if (info == null) {
      return DocValues.emptyBinary();
    } else if (info.hasDocValues()) {
      throw new IllegalStateException("Type mismatch: " + field + " was indexed as " + info.getDocValuesType());
    } else if (!info.isIndexed()) {
      return DocValues.emptyBinary();
    }

    BinaryDocValuesImpl impl = (BinaryDocValuesImpl) caches.get(BinaryDocValues.class).get(reader, new CacheKey(field, acceptableOverheadRatio), setDocsWithField);
    return impl.iterator();
  }

你可能感兴趣的:(Lucene,缓存,存储)