使用 20 M 记录的 Lucene 索引需要更多时间
Lucene Indexing with 20 M Records taking more time
我有以下用于索引的 Lucene 代码,当我 运行 这段代码有 100 万条记录时 - 它 运行ning 很快(在 15 秒内建立索引(本地和高配置的服务器) ).
当我尝试索引 2000 万条记录时,大约需要 10 分钟才能完成索引。
我 运行 在 Linux 服务器上使用超过 100 GB RAM 存储这 2000 万条记录。在这种情况下,设置更多 RAM 缓冲区大小会有所帮助吗?如果是,在我的情况下可以设置多少 RAM 大小(我有超过 100 GB 的 RAM)
我在我的本地机器(8 GB RAM)中尝试了相同的 2000 万条记录,它花费了相同的十分钟,我尝试在本地设置 1 GB RAM 缓冲区大小相同的 10 分钟,没有设置任何 RAM 缓冲区也相同在我的本地机器上 2000 万条记录需要 10 分钟。
我在linux中尝试过不设置RAM缓冲区大小,2000万条记录花了大约8分钟。
final File docDir = new File(docsPath.getFile().getAbsolutePath());
LOG.info("Indexing to directory '" + indexPath + "'...");
Directory dir = FSDirectory.open(new File(indexPath.getFile().getAbsolutePath()));
Analyzer analyzer = null;
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, analyzer);
iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
iwc.setRAMBufferSizeMB(512.0);
IndexWriter indexWriter = new IndexWriter(dir, iwc);
if (docDir.canRead()) {
if (docDir.isDirectory()) {
String[] files = docDir.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = new File(docDir, files[i]);
String filePath = file.getPath();
String delimiter = BatchUtil.getProperty("file.delimiter");
if (filePath.indexOf("ecid") != -1) {
indexEcidFile(indexWriter, file, delimiter);
} else if (filePath.indexOf("entity") != -1) {
indexEntityFile(indexWriter, file, delimiter);
}
}
}
}
}
indexWriter.forceMerge(2);
indexWriter.close();
以及用于索引的方法之一:
private void indexEntityFile(IndexWriter writer, File file, String delimiter) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
Document doc = new Document();
Field four_pk_Field = new StringField("four_pk", "", Field.Store.NO);
doc.add(four_pk_Field);
Field cust_grp_cd_Field = new StoredField("cust_grp_cd", "");
Field cust_grp_mbrp_id_Field = new StoredField("cust_grp_mbrp_id", "");
doc.add(cust_grp_cd_Field);
doc.add(cust_grp_mbrp_id_Field);
String line = null;
while ((line = br.readLine()) != null) {
String[] lineTokens = line.split("\" + delimiter);
four_pk_Field.setStringValue(four_pk);
String cust_grp_cd = lineTokens[4];
cust_grp_cd_Field.setStringValue(cust_grp_cd);
String cust_grp_mbrp_id = lineTokens[5];
cust_grp_mbrp_id_Field.setStringValue(cust_grp_mbrp_id);
writer.addDocument(doc);
}
br.close();
} catch (FileNotFoundException fnfe) {
LOG.error("", fnfe);
} catch (IOException ioe) {
LOG.error("", ioe);
} finally {
try {
fis.close();
} catch (IOException e) {
LOG.error("", e);
}
}
}
有什么想法吗?
发生这种情况是因为您尝试在 1 次提交中索引所有 2000 万个文档(并且 Lucene 需要在内存中保存所有 2000 万个文档)。应该做些什么来修复它 - 是添加
writer.commit()
在indexEntityFile方法中,每X添加文件。 X 可以是 100 万或类似
代码可能如下所示(只是展示方法,您需要根据需要修改此代码)
int numberOfDocsInBatch = 0;
...
writer.addDocument(doc);
numberOfDocsInBatch ++;
if (numberOfDocsInBatch == 1_000_000) {
writer.commit();
numberOfDocsInBatch = 0;
}
我有以下用于索引的 Lucene 代码,当我 运行 这段代码有 100 万条记录时 - 它 运行ning 很快(在 15 秒内建立索引(本地和高配置的服务器) ).
当我尝试索引 2000 万条记录时,大约需要 10 分钟才能完成索引。
我 运行 在 Linux 服务器上使用超过 100 GB RAM 存储这 2000 万条记录。在这种情况下,设置更多 RAM 缓冲区大小会有所帮助吗?如果是,在我的情况下可以设置多少 RAM 大小(我有超过 100 GB 的 RAM)
我在我的本地机器(8 GB RAM)中尝试了相同的 2000 万条记录,它花费了相同的十分钟,我尝试在本地设置 1 GB RAM 缓冲区大小相同的 10 分钟,没有设置任何 RAM 缓冲区也相同在我的本地机器上 2000 万条记录需要 10 分钟。
我在linux中尝试过不设置RAM缓冲区大小,2000万条记录花了大约8分钟。
final File docDir = new File(docsPath.getFile().getAbsolutePath());
LOG.info("Indexing to directory '" + indexPath + "'...");
Directory dir = FSDirectory.open(new File(indexPath.getFile().getAbsolutePath()));
Analyzer analyzer = null;
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, analyzer);
iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
iwc.setRAMBufferSizeMB(512.0);
IndexWriter indexWriter = new IndexWriter(dir, iwc);
if (docDir.canRead()) {
if (docDir.isDirectory()) {
String[] files = docDir.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = new File(docDir, files[i]);
String filePath = file.getPath();
String delimiter = BatchUtil.getProperty("file.delimiter");
if (filePath.indexOf("ecid") != -1) {
indexEcidFile(indexWriter, file, delimiter);
} else if (filePath.indexOf("entity") != -1) {
indexEntityFile(indexWriter, file, delimiter);
}
}
}
}
}
indexWriter.forceMerge(2);
indexWriter.close();
以及用于索引的方法之一:
private void indexEntityFile(IndexWriter writer, File file, String delimiter) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
Document doc = new Document();
Field four_pk_Field = new StringField("four_pk", "", Field.Store.NO);
doc.add(four_pk_Field);
Field cust_grp_cd_Field = new StoredField("cust_grp_cd", "");
Field cust_grp_mbrp_id_Field = new StoredField("cust_grp_mbrp_id", "");
doc.add(cust_grp_cd_Field);
doc.add(cust_grp_mbrp_id_Field);
String line = null;
while ((line = br.readLine()) != null) {
String[] lineTokens = line.split("\" + delimiter);
four_pk_Field.setStringValue(four_pk);
String cust_grp_cd = lineTokens[4];
cust_grp_cd_Field.setStringValue(cust_grp_cd);
String cust_grp_mbrp_id = lineTokens[5];
cust_grp_mbrp_id_Field.setStringValue(cust_grp_mbrp_id);
writer.addDocument(doc);
}
br.close();
} catch (FileNotFoundException fnfe) {
LOG.error("", fnfe);
} catch (IOException ioe) {
LOG.error("", ioe);
} finally {
try {
fis.close();
} catch (IOException e) {
LOG.error("", e);
}
}
}
有什么想法吗?
发生这种情况是因为您尝试在 1 次提交中索引所有 2000 万个文档(并且 Lucene 需要在内存中保存所有 2000 万个文档)。应该做些什么来修复它 - 是添加
writer.commit()
在indexEntityFile方法中,每X添加文件。 X 可以是 100 万或类似
代码可能如下所示(只是展示方法,您需要根据需要修改此代码)
int numberOfDocsInBatch = 0;
...
writer.addDocument(doc);
numberOfDocsInBatch ++;
if (numberOfDocsInBatch == 1_000_000) {
writer.commit();
numberOfDocsInBatch = 0;
}