关于索引删除的策略IndexDeletionPolicy 。
public IndexWriter(Directory d, Analyzer a, boolean create)
throws CorruptIndexException, LockObtainFailedException, IOException { init(d, a, create, false, null, true); }构造一个IndexWriter需要调用init()方法进行初始化,init()方法的声明如下所示:
/**
* 该方法中的参数列表中。各个参数的含义如下: * d :指定的存放建立索引文件的索引目录 * a :一个传递进来分析器 * create :是否要重新写入索引文件,如果为true,则重写索引文件;如果为false,则追加写入索引文件 * closeDir :一个boolean型变量,表示是否关闭索引目录Directory d,它是IndexWriter的一个成员变量 * deletionPolicy :指定删除索引文件使用的策略 * autoCommit :建立索引文件后,不对已经存在的索引进行Clone,自动提交。 */private void init(Directory d, Analyzer a, final boolean create, boolean closeDir, IndexDeletionPolicy deletionPolicy, boolean autoCommit)
throws CorruptIndexException, LockObtainFailedException, IOExceptionIndexDeletionPolicy是一个接口,是有关在建立索引的过程中,对索引文件进行灵活地(删除)操作的一种自定义接口。可以在合适的时机进行删除操作,可以指定删除的时刻,完全可以根据自己的需要进行定制,但是,这可能会造成存储开销,但是相对于删除操作策略的灵活便利性,这也是比较值得的。
IndexDeletionPolicy接口的定义非常简单,而且为我们做了启发式的指引:
package org.apache.lucene.index;
import java.util.List;
import java.io.IOException;// 该接口示例了两种删除索引文件的时机,即所谓的Points
public interface IndexDeletionPolicy {
// 一个IndexWriter索引器初始化的时候,可以删除一些时刻(提交点)提交的索引文件,这些提交点存放在一个List中,包括最早提交点和最近的提点之间的所有提交点,当然,删除他们是可选的,而且应当慎重,因为一旦删除便不可回滚。
public void onInit(List commits) throws IOException;// 当新建的索引写入目录,并已经提交的时候,我们仍然可以删除指定List中一些时刻(提交点)提交的索引文件,当然,删除他们是可选的,而且应当慎重
public void onCommit(List commits) throws IOException; }IndexDeletionPolicy接口的实现类如图所示:
通过对IndexDeletionPolicy接口的实现类进行学习,把握最基本的索引删除的动机和行为。通过IndexDeletionPolicy接口的实现类的类名就可以大概了解到它的索引删除策略:
1、KeepOnlyLastCommitDeletionPolicy策略
KeepOnlyLastCommitDeletionPolicy类在初始化一个IndexWriter的时候,在init方法中如果指定IndexDeletionPolicy deletionPolicy为null,则默认的索引删除策略为KeepOnlyLastCommitDeletionPolicy。
KeepOnlyLastCommitDeletionPolicy类的源代码非常容易理解,如下所示:
package org.apache.lucene.index;
import java.util.List;
public final class KeepOnlyLastCommitDeletionPolicy implements IndexDeletionPolicy {
// 初始化IndexWriter的时候,除了保留最近的一个提交点以外,删除所有提交点提交的索引文件
public void onInit(List commits) { // Note that commits.size() should normally be 1: onCommit(commits); }// 除了最近时刻的提交点保留以外,其余的全部删除
public void onCommit(List commits) { // Note that commits.size() should normally be 2 (if not // called by onInit above): int size = commits.size(); for(int i=0;i<size-1;i++) { // IndexCommitPoint也很重要,因为它涉及到了索引段,比较复杂,在后面系统学习 ((IndexCommitPoint) commits.get(i)).delete(); } } }
2、KeepNoneOnInitDeletionPolicy策略
初始化时删除所有提交点的索引段,最后提交的时候,保留最近提交点的索引段。
class KeepNoneOnInitDeletionPolicy implements IndexDeletionPolicy {
int numOnInit; int numOnCommit; public void onInit(List commits) { verifyCommitOrder(commits); numOnInit++; // 初始化的时候,就删除所有的提交点 Iterator it = commits.iterator(); while(it.hasNext()) { ((IndexCommitPoint) it.next()).delete(); } } public void onCommit(List commits) {// 验证每个提交点提交的索引文件(索引段)名称的正确性
verifyCommitOrder(commits); int size = commits.size(); // 除了最近时刻的提交点保留以外,其余的全部删除 for(int i=0;i<size-1;i++) { ((IndexCommitPoint) commits.get(i)).delete(); } numOnCommit++; } }3、KeepAllDeletionPolicy策略
保留所有提交点,不删除任何提交点的索引段。
class KeepAllDeletionPolicy implements IndexDeletionPolicy {
int numOnInit; int numOnCommit; public void onInit(List commits) { verifyCommitOrder(commits); numOnInit++; } public void onCommit(List commits) { verifyCommitOrder(commits); numOnCommit++; } }4、KeepLastNDeletionPolicy策略
初始化时,不删除任何提交点;最后提交时,保留指定的最近的N个提交点。
class KeepLastNDeletionPolicy implements IndexDeletionPolicy {
int numOnInit; int numOnCommit; int numToKeep; int numDelete; Set seen = new HashSet(); // Set seen用于保证不重复删除某个提交点public KeepLastNDeletionPolicy(int numToKeep) { // 初始化显式指定最近提交点的个数
this.numToKeep = numToKeep; }public void onInit(List commits) {
verifyCommitOrder(commits); numOnInit++; // false指定了不做任何删除 doDeletes(commits, false); }public void onCommit(List commits) {
verifyCommitOrder(commits); doDeletes(commits, true); // 根据初始化的numToKeep,保留最近numToKeep个提交点 } private void doDeletes(List commits, boolean isCommit) { if (isCommit) { String fileName = ((IndexCommitPoint) commits.get(commits.size()-1)).getSegmentsFileName(); if (seen.contains(fileName)) { throw new RuntimeException("onCommit was called twice on the same commit point: " + fileName); } seen.add(fileName); // seen中加入的是已经删除的提交点 numOnCommit++; } int size = commits.size(); for(int i=0;i<size-numToKeep;i++) { // 删除前size-numToKeep个提交点 ((IndexCommitPoint) commits.get(i)).delete(); numDelete++; } } }5、ExpirationTimeDeletionPolicy策略
如果某个提交的响应已经超过指定时间,则删除掉这个提交点。
class ExpirationTimeDeletionPolicy implements IndexDeletionPolicy {
Directory dir;
double expirationTimeSeconds; // 指定提交超时时间 int numDelete;public ExpirationTimeDeletionPolicy(Directory dir, double seconds) {
this.dir = dir; this.expirationTimeSeconds = seconds; }public void onInit(List commits) throws IOException {
verifyCommitOrder(commits); onCommit(commits); }public void onCommit(List commits) throws IOException {
verifyCommitOrder(commits);IndexCommitPoint lastCommit = (IndexCommitPoint) commits.get(commits.size()-1);
// 根据索引文件的最后提交时间
double expireTime = dir.fileModified(lastCommit.getSegmentsFileName())/1000.0 - expirationTimeSeconds;Iterator it = commits.iterator();
while(it.hasNext()) {
IndexCommitPoint commit = (IndexCommitPoint) it.next(); double modTime = dir.fileModified(commit.getSegmentsFileName())/1000.0; if (commit != lastCommit && modTime < expireTime) { commit.delete(); numDelete += 1; } } } }上面五种删除策略,主要地,无非是在索引器初始化的时刻和建立索引提交的时刻,来选择是否删除提交点。