创建自定义索引

基本概念

ID

每一个索引类型都必须有一个ID变量作为其唯一标识符。这一名称将用于CLI,服务器配置,存储索引的文件路径中等各种场合,用于唯一地确定这一索引类型。

Index接口的getID()方法会将索引的ID返回给它的使用者。

Level (数据)层级

启发式索引用各种不同的方法,存储了在原始数据之外额外并且通常更小的信息,用于提高随机查询的效率。因此,每一条索引都必须有它作用的数据域范围。例如,如果一个索引 记录了数据集的”最大”数值,那这一”最大”数值必须拥有它作用的范围(可以是一组数据行,也可以是一个数据分区,甚至整张数据表的最大值)。当创建一个新的索引类型是,必须 实现Set<Level> getSupportedIndexLevels(); 方法来告知它可以支持的数据层级。这些层级由Index接口中的一个枚举类型定义。

接口概览

索引方法

除了上面提到的方法以外,这一段落将介绍其他几个实现新索引类型最重要的方法。要获取Index接口的完整文档,请参阅源代码的Java Doc。

Index接口有两个最重要的方法:

  1. boolean matches(Object expression) throws UnsupportedOperationException;
  2. <I> Iterator<I> lookUp(Object expression) throws UnsupportedOperationException;

第一个matches()方法接收一个表达式对象,并返回基于索引存储的信息,表达式对应的数据是否可能存在。例如,如果一个索引标记了数据中的最大值,那他可以容易地判断col_val > 5是否可能成立。

第二个方法lookUp()不是必须的。在返回数据是否可能存在以外,他还能返回一个迭代器来返回数据可能存在的位置。对于一个索引,它的matches()方法和lookUp().hasNext()应当总是返回相同的结果。

插入和存取索引

下面的几个方法用于向一个索引中添加值,以及在磁盘上存储/读取索引实例:

  1. boolean addValues(Map<String, List<Object>> values) throws IOException;
  2. Index deserialize(InputStream in) throws IOException;
  3. void serialize(OutputStream out) throws IOException;

这些方法的使用非常直观。为了更好地理解他们的用法,MinMaxIndex的源代码可以作为一个很好的例子。在这个索引中,添加数据仅仅需要通过新的数据更新maxmin变量即可。 serialize()/deserialize()方法则只需要向/从磁盘写入/读取最大和最小值这两个值。