關于索引刪除的策略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, IOException
IndexDeletionPolicy是一個接口,是有關在建立索引的過程中,對索引文件進行靈活地(刪除)操作的一種自定義接口。可以在合適的時機進行刪除操作,可以指定刪除的時刻,完全可以根據自己的需要進行定制,但是,這可能會造成存儲開銷,但是相對于刪除操作策略的靈活便利性,這也是比較值得的。
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;
??????? }
????? }
??? }
}
上面五種刪除策略,主要地,無非是在索引器初始化的時刻和建立索引提交的時刻,來選擇是否刪除提交點。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
