आप क्या गलत कर रहे हैं यह मानते हुए कि लुसेन के built-in transactional capabilities में एक विशिष्ट संबंधपरक डेटाबेस की तुलना में प्रदर्शन और गारंटी है, जब they really don't। अधिक विशेष रूप से आपके मामले में, एक प्रतिबद्धता डिस्क के साथ सभी इंडेक्स फ़ाइलों को सिंक करता है, जिससे सूचकांक आकार के अनुपात में आनुपातिक समय होता है। यही कारण है कि समय के साथ आपके indexWriter.commit()
अधिक से अधिक समय लगता है। ,
यह एक महंगा ऑपरेशन हो सकता है तो आप अपने आवेदन में लागत का परीक्षण और यह कर केवल जब वास्तव में जरूरी चाहिए: IndexWriter.commit()
के लिए Javadoc भी चेतावनी दी है कि।
क्या आप डेटाबेस दस्तावेज की कल्पना कर सकते हैं जो आपको काम करने से बचने के लिए कह रहा है?
आपका मुख्य लक्ष्य के बाद से एक समय पर ढंग डेटाबेस दिखाई अद्यतन करता है रखने के लिए Lucene खोजों के माध्यम से, स्थिति में सुधार करने लगती है, निम्न कार्य करें:
indexWriter.deleteDocuments(..)
है और indexWriter.addDocument(..)
ट्रिगर के बाद एक सफल डेटाबेस के लिए प्रतिबद्ध, के पहले
- प्रदर्शन करना
indexWriter.commit()
हर लेन-देन के समय-समय पर बजाय, बस आपके बदलावों के अंत में डिस्क
- खोज के लिए उपयोग एक
SearcherManager
लिए लिखा जाता है बनाने के लिए और करने के लिए समय-समय पर maybeRefresh()
आह्वान करने के लिए बजाय एक उचित समय सीमा
निम्नलिखित उदाहरण प्रोग्राम है जो दर्शाता है कि समय-समय पर maybeRefresh()
प्रदर्शन करके दस्तावेज़ अपडेट कैसे पुनर्प्राप्त किए जा सकते हैं। यह 100000 दस्तावेजों का सूचकांक बनाता है, का उपयोग commit()
और maybeRefresh()
के आवधिक आमंत्रण को सेट करने के लिए करता है, आपको एक दस्तावेज़ को अपडेट करने के लिए संकेत देता है, फिर अपडेट दिखाई देने तक बार-बार खोज करता है। कार्यक्रम समाप्त होने पर सभी संसाधनों को ठीक से साफ किया जाता है। ध्यान दें कि अद्यतन दिखाई देने पर नियंत्रण कारक तब होता है जब maybeRefresh()
लागू होता है, commit()
नहीं।
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.concurrent.*;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.FSDirectory;
public class LucenePeriodicCommitRefreshExample {
ScheduledExecutorService scheduledExecutor;
MyIndexer indexer;
MySearcher searcher;
void init() throws IOException {
scheduledExecutor = Executors.newScheduledThreadPool(3);
indexer = new MyIndexer();
indexer.init();
searcher = new MySearcher(indexer.indexWriter);
searcher.init();
}
void destroy() throws IOException {
searcher.destroy();
indexer.destroy();
scheduledExecutor.shutdown();
}
class MyIndexer {
IndexWriter indexWriter;
Future commitFuture;
void init() throws IOException {
indexWriter = new IndexWriter(FSDirectory.open(Paths.get("C:\\Temp\\lucene-example")), new IndexWriterConfig(new StandardAnalyzer()));
indexWriter.deleteAll();
for (int i = 1; i <= 100000; i++) {
add(String.valueOf(i), "whatever " + i);
}
indexWriter.commit();
commitFuture = scheduledExecutor.scheduleWithFixedDelay(() -> {
try {
indexWriter.commit();
} catch (IOException e) {
e.printStackTrace();
}
}, 5, 5, TimeUnit.MINUTES);
}
void add(String id, String text) throws IOException {
Document doc = new Document();
doc.add(new StringField("id", id, Field.Store.YES));
doc.add(new StringField("text", text, Field.Store.YES));
indexWriter.addDocument(doc);
}
void update(String id, String text) throws IOException {
indexWriter.deleteDocuments(new Term("id", id));
add(id, text);
}
void destroy() throws IOException {
commitFuture.cancel(false);
indexWriter.close();
}
}
class MySearcher {
IndexWriter indexWriter;
SearcherManager searcherManager;
Future maybeRefreshFuture;
public MySearcher(IndexWriter indexWriter) {
this.indexWriter = indexWriter;
}
void init() throws IOException {
searcherManager = new SearcherManager(indexWriter, true, null);
maybeRefreshFuture = scheduledExecutor.scheduleWithFixedDelay(() -> {
try {
searcherManager.maybeRefresh();
} catch (IOException e) {
e.printStackTrace();
}
}, 0, 5, TimeUnit.SECONDS);
}
String findText(String id) throws IOException {
IndexSearcher searcher = null;
try {
searcher = searcherManager.acquire();
TopDocs topDocs = searcher.search(new TermQuery(new Term("id", id)), 1);
return searcher.doc(topDocs.scoreDocs[0].doc).getField("text").stringValue();
} finally {
if (searcher != null) {
searcherManager.release(searcher);
}
}
}
void destroy() throws IOException {
maybeRefreshFuture.cancel(false);
searcherManager.close();
}
}
public static void main(String[] args) throws IOException {
LucenePeriodicCommitRefreshExample example = new LucenePeriodicCommitRefreshExample();
example.init();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
example.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
});
try (Scanner scanner = new Scanner(System.in)) {
System.out.print("Enter a document id to update (from 1 to 100000): ");
String id = scanner.nextLine();
System.out.print("Enter what you want the document text to be: ");
String text = scanner.nextLine();
example.indexer.update(id, text);
long startTime = System.nanoTime();
String foundText;
do {
foundText = example.searcher.findText(id);
} while (!text.equals(foundText));
long elapsedTimeMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
System.out.format("it took %d milliseconds for the searcher to see that document %s is now '%s'\n", elapsedTimeMillis, id, text);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}
}
}
यह उदाहरण सफलतापूर्वक लुसीन 5.3.1 और जेडीके 1.8.0_66 का उपयोग करके परीक्षण किया गया था।
क्या आप इसे बैकग्राउंड कार्यों के साथ ठीक कर सकते हैं? आपके पास शायद 10 सेकंड्स जुर्माना होगा, लेकिन यह कई अनुप्रयोगों के लिए ठीक हो सकता है – AdamSkywalker
@AdamSkywalker - लेकिन यह धीमा और धीमा हो जाता है, जब 1hr, या 10hrs, या 2 दिन लगते हैं तो क्या होता है? –