Я разработал свой собственный Indexer в Lucene 5.2.1. Я пытаюсь индексировать файл размером 1,5 ГБ, и мне нужно сделать некоторые нетривиальные вычисления во время индексации на каждом отдельном документе коллекции.Оптимизация индексации lucene 5.2.1
Проблема в том, что для индексирования требуется почти 20 минут! Я следил за этим очень полезным wiki, но он все еще слишком медленный. Я попытался увеличить пространство кучи Eclipse и java-память VM, но это скорее вопрос жесткого диска, а не виртуальной памяти (я использую ноутбук с 6 ГБ или оперативной памятью и обычный жесткий диск).
Я читал об этом discussion, который предлагает использовать RAMDirectory или установить RAM-диск. Проблема с RAM-диском будет связана с сохраняющимся индексом в моей файловой системе (я не хочу потерять индексы после перезагрузки). Проблема с RAMDirectory вместо является то, что, в соответствии с API-интерфейсов, я не должен использовать его, потому что мой индекс больше, чем «несколько сотен megabites» ...
Предупреждение: Этот класс не предназначен для работы с огромным индексов. Все, кроме нескольких сотен мегабайт, будет тратить ресурсы (GC-циклы), поскольку использует внутренний размер буфера 1024 байта, создавая миллионы байт [1024] массивов. Этот класс оптимизирован для небольших резидентных индексов памяти. Он также имеет плохой параллелизм в многопоточных средах.
Здесь вы можете найти свой код:
общественного класса ReviewIndexer {
private JSONParser parser;
private PerFieldAnalyzerWrapper reviewAnalyzer;
private IndexWriterConfig iwConfig;
private IndexWriter indexWriter;
public ReviewIndexer() throws IOException{
parser = new JSONParser();
reviewAnalyzer = new ReviewWrapper().getPFAWrapper();
iwConfig = new IndexWriterConfig(reviewAnalyzer);
//change ram buffer size to speed things up
//@url https://wiki.apache.org/lucene-java/ImproveIndexingSpeed
iwConfig.setRAMBufferSizeMB(2048);
//little speed increase
iwConfig.setUseCompoundFile(false);
//iwConfig.setMaxThreadStates(24);
// Set to overwrite the existing index
indexWriter = new IndexWriter(FileUtils.openDirectory("review_index"), iwConfig);
}
/**
* Indexes every review.
* @param file_path : the path of the yelp_academic_dataset_review.json file
* @throws IOException
* @return Returns true if everything goes fine.
*/
public boolean indexReviews(String file_path) throws IOException{
BufferedReader br;
try {
//open the file
br = new BufferedReader(new FileReader(file_path));
String line;
//define fields
StringField type = new StringField("type", "", Store.YES);
String reviewtext = "";
TextField text = new TextField("text", "", Store.YES);
StringField business_id = new StringField("business_id", "", Store.YES);
StringField user_id = new StringField("user_id", "", Store.YES);
LongField stars = new LongField("stars", 0, LanguageUtils.LONG_FIELD_TYPE_STORED_SORTED);
LongField date = new LongField("date", 0, LanguageUtils.LONG_FIELD_TYPE_STORED_SORTED);
StringField votes = new StringField("votes", "", Store.YES);
Date reviewDate;
JSONObject jsonVotes;
try {
indexWriter.deleteAll();
//scan the file line by line
//TO-DO: split in chunks and use parallel computation
while ((line = br.readLine()) != null) {
try {
JSONObject jsonline = (JSONObject) parser.parse(line);
Document review = new Document();
//add values to fields
type.setStringValue((String) jsonline.get("type"));
business_id.setStringValue((String) jsonline.get("business_id"));
user_id.setStringValue((String) jsonline.get("user_id"));
stars.setLongValue((long) jsonline.get("stars"));
reviewtext = (String) jsonline.get("text");
//non-trivial function being calculated here
text.setStringValue(reviewtext);
reviewDate = DateTools.stringToDate((String) jsonline.get("date"));
date.setLongValue(reviewDate.getTime());
jsonVotes = (JSONObject) jsonline.get("votes");
votes.setStringValue(jsonVotes.toJSONString());
//add fields to document
review.add(type);
review.add(business_id);
review.add(user_id);
review.add(stars);
review.add(text);
review.add(date);
review.add(votes);
//write the document to index
indexWriter.addDocument(review);
} catch (ParseException | java.text.ParseException e) {
e.printStackTrace();
br.close();
return false;
}
}//end of while
} catch (IOException e) {
e.printStackTrace();
br.close();
return false;
}
//close buffer reader and commit changes
br.close();
indexWriter.commit();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
return false;
}
System.out.println("Done.");
return true;
}
public void close() throws IOException {
indexWriter.close();
}
}
Что лучше всего делать? Должен ли я создать RAM-диск, а затем скопировать индексы в FileSystem после их завершения или использовать RAMDirectory в любом случае или, возможно, что-то еще? Большое спасибо
Профилировали ли вы свой код, чтобы узнать, какая часть занимает больше всего времени? Я подозреваю, что фактическое индексирование не медленное, а процесс чтения файлов. – user1071777
Вам нужно прочитать файл последовательным образом? Если нет, вы можете ускорить работу с распараллеливанием, разбивая файл на куски и вычисляя куски в каждом процессе. – cheffe
Кроме того, если у вас есть в основном уникальные термины, индексирование будет медленнее и медленнее. Можете ли вы предоставить дополнительную информацию о полях/условиях, которые вы хотите индексировать? – RobAu