Индекс Lucene застрял после ~ 1 миллиона файлов (файл nrm становится все больше и больше ...) - PullRequest
1 голос
/ 25 июня 2011

Кто-нибудь знает, почему это происходит?Я делаю базовую индексацию + SAX-разбор XML-файлов и добавляю каждый путь в качестве нового поля в документе.Мне нравятся 1,5 миллиона файлов, и он зависает на этом одном файле на 30 минут, и .nrm (нормализующий файл ??) становится все больше и больше.

Я не знаю, почему это происходит, мой IndexWriterимеет форму:

writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_30), IndexWriter.MaxFieldLength.UNLIMITED)

Разве это не оптимально для больших индексов?Почему он заморожен в этом файле?Я запускал его несколько раз с более чем 1 миллионом XML-файлов, и он постоянно зависал в разных XML-файлах (не только этот, в частности, чья структура в порядке).

Редактировать:

Итак, скажем, я индексирую файлы 2000 одновременно с помощью отдельных команд Java.После завершения индексации и вызова метода close indexwriter, мне что-то не хватает, если я хочу переписать этот индекс?Должен ли я оптимизировать индекс?Мне кажется, я вспоминаю, как Lucene in Action говорил об оптимизации, если вы не будете писать в нее какое-то время.

На самом деле этот метод работал для 1,8 миллиона файлов, но после того, как я попытался добавить больше в партиях 2000 года, этот файл NRM и еще один записали около 70 ГБ!Почему память JVM исчерпывается, если функция индексации java Lucene вызывается только в партиях 2000 года?Это не похоже на сбор мусора, если только мне не нужно добавить что-то в код Lucene перед тем, как закрыть средство записи индекса.

Редактировать 2:

У меня около 4 миллионовXML-файлы, которые выглядят следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<person>
   <name>Candice Archie
   </name>
   <filmography>
      <direct>
         <movie>
            <title>Lucid (2006) (V)
            </title>
            <year>2006
            </year>
         </movie>
      </direct>
      <write>
         <movie>
            <title>Lucid (2006) (V)
            </title>
            <year>2006
            </year>
         </movie>
      </write>
      <edit>
         <movie>
            <title>Lucid (2006) (V)
            </title>
            <year>2006
            </year>
         </movie>
      </edit>
      <produce>
         <movie>
            <title>Lucid (2006) (V)
            </title>
            <year>2006
            </year>
         </movie>
      </produce>
   </filmography>
</person>

Я анализирую эти XML-файлы и добавляю содержимое в поле пути, например / person / produk / movie / movie / title, Lucid (2006) (V)

Дело в том, что я рассчитываю вычислять статистику частоты данного термина в экземплярах полей документа для каждого документа в индексе (затем суммировать это значение по всем документам) ...так что если бы было два экземпляра / персона / продюсер / фильмография / фильм / название и оба содержали "Lucid", я бы хотел два.tf (t в d), которое дает Lucene, даст 3, если был другой путь (например: / person / name: Lucid), но не делает этого для терминов в похожих полях документа.

СердцеИндексирование Lucene делает это:

public void endElement( String namespaceURI,String localName,String qName ) throws SAXException {
  if(this.ignoreTags.contains(localName)){
      ignoredArea = false;
      return;
  }
  String newContent = content.toString().trim();
  if(!empty.equals(newContent) && newContent.length()>1)
  {
      StringBuffer stb = new StringBuffer();
      for(int i=0; i<currpathname.size();i++){
      //System.out.println(i + "th iteration of loop. value:" + currpathname.get(i).toString() + k + "th call.");
      stb.append("/");
      stb.append(currpathname.get(i));
      }
      //stb.append("0");
      if(big.get(stb.toString())==null){
          big.put(stb.toString(), 1);
      }
      else{
          big.put(stb.toString(),big.get(stb.toString())+1);
      }
      if(map.get(stb.toString())==null){
          map.put(stb.toString(),0);
          stb.append(map.get(stb.toString())); //ADDED THIS FOR ZERO
      }
      else
      {
          map.put(stb.toString(),map.get(stb.toString())+1);
          stb.append(map.get(stb.toString()));
      }
      doc.add(new Field(stb.toString(),newContent,Field.Store.YES, Field.Index.ANALYZED));
      seenPaths.add(stb);
      //System.out.println(stb.toString());// This will print all fields indexed for each document (separating nonunique [e.x.: /person/name0 /person/name1]
      //System.out.println(newContent);
  }
  currpathname.pop();   
  content.delete(0,content.length()); //clear content
  //This method adds to the Lucene index the field of the unfolded Stack variable currpathname and the value in content (whitespace trimmed).

}

Map и BigMap являются хеш-картами (не беспокойтесь о bigmap, он используется для чего-то другого. map создается всякий раз, когда новый XMLсоздается файл (объект документа) .Есть метод endDocument (), который добавляет документ после вызова всех методов startElement, endElement и символьных (это методы синтаксического анализатора Xerces)

  public void endDocument( ) throws SAXException {
  try {
      numIndexed++;
    writer.addDocument(doc);
} catch (CorruptIndexException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
  }

Извините задлинный пост - спасибо за вашу помощь! Кроме того, я не думаю, что проблема с сервером. Я запустил код для 4 миллионов файлов одновременно, и он исчерпал кучу памяти, даже когда я использовал Xmx12000M Xms12000M

это мощный сервер, поэтому он может определенно справиться с этим ...

Редактировать 3:

Привет еще раз! Спасибо, и вы правы. Вероятно, Lucene не был создан для этого.Мы действуемсоюзник собирается проводить другие эксперименты, но я думаю, что решил проблему с помощью ваших идей и некоторых других.Во-первых, я перестал нормализовать поля, и это уменьшило размер индекса много раз.Кроме того, я играл с методами mergedocs и rambuffer и увеличил их.Индексирование значительно улучшилось.Я отвечу на вопрос с твоей помощью :) Спасибо.

1 Ответ

1 голос
/ 25 июня 2011

Попробуйте индексацию партиями. Нижеследующий код должен дать вам представление, как это сделать. Также я бы порекомендовал ознакомиться с последней версией Lucene in Action.

Скорее всего, вы перегружаете сборщик мусора (при условии отсутствия утечек памяти, которые трудно найти), что в конечном итоге должно привести к ошибке нехватки памяти.

    private static final int FETCH_SIZE = 100;
    private static final int BATCH_SIZE = 1000;

    //Scrollable results will avoid loading too many objects in memory
    ScrollableResults scroll = query.scroll(ScrollMode.FORWARD_ONLY);
    int batch = 0;
    scroll.beforeFirst();
    while (scroll.next()) {
        batch++;

        index(scroll.get(0)); //index each element

        if (batch % BATCH_SIZE == 0) {
            //flushToIndexes(); //apply changes to indexes
            //optimize();
            //clear(); //free memory since the queue is processed
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...