К моему удивлению, я обнаружил, что индексация документов в механизм полнотекстового поиска в H2 сравнительно медленная, и я хотел бы ускорить это.
Я использую версию в памятиH2, что делает этот случай особенно удивительным.
Некоторые тесты, использующие небольшие документы размером 100 КБ (только заголовок и некоторые теги):
- При использовании
org.h2.fulltext.FullTextLucene.init
для индексации требуется ~ 15 с. - Использование
org.h2.fulltext.FullText.init
не вносит изменений. - Только одна вставка SQL (т. Е. Полнотекстовая индексация отключена) занимает всего 1 с.
- При использовании Elasticsearch (с массовой индексацией) я быожидайте, что эта сумма будет обработана и будет доступна для поиска в течение 3 секунд, то есть она даже будет сохранена на диске.
Некоторая дополнительная информация, которая может помочь:
- Соединение используется повторно.
- Не используются стоп-слова (но это не будет иметь большого значения с точки зрения размера документов).EDIT_2: я добавил большой список стоп-слов (> 100).Это сделало его примерно на 10% быстрее (от ~ 15 с до ~ 14 с).
- Одна только вставка SQL (т.е. полнотекстовая индексация отключена) занимает всего 1 с, поэтому проблема должна быть с индексацией полнотекстового поиска.
- Официальный учебник и страница о производительности , похоже, не предлагают решения.
- Кажется, что нет возможности для массовыхиндексирование, как в Elasticsearch.
- EDIT_1: я также попытался создать таблицу SQL и вставить FIRST (что занимает 1 с), а ПОСЛЕ ТОГО, создать индекс полнотекстового поиска и запустить
FullTextLucene.reindex()
.Но это делает процесс еще немного медленнее.
Если вам нужна помощь, вот код создания индекса и вставок:
Создание индекса:
private void createTablesAndLuceneIndex() {
try {
final Statement statement = this.createStatement();
statement.execute("CREATE ALIAS IF NOT EXISTS FT_INIT FOR \"org.h2.fulltext.FullTextLucene.init\"");
statement.execute("CALL FT_INIT()");
// FullTextLucene.setIgnoreList(this.conn, "to,this"); // Do we need stop words?
FullTextLucene.setWhitespaceChars(this.conn, " ,.-");
// Set up SQL table & Lucene index
statement.execute("CREATE TABLE " + PNS_VIDEOS + "(ID INT PRIMARY KEY, TITLE VARCHAR, TAGS VARCHAR, ACTORS VARCHAR)");
statement.execute("CALL FT_CREATE_INDEX('PUBLIC', '" + PNS_VIDEOS + "', NULL)");
// Close statement
statement.close();
} catch (final SQLException e) {
throw new SqlTableCreationException(e); // todo logging?!
}
}
Индексный документ:
public void index(final PnsVideo pnsVideo) {
try (PreparedStatement statement = this.conn.prepareStatement("INSERT INTO " + PNS_VIDEOS + " VALUES(?, ?, ?, ?)")) {
statement.setInt(1, this.autoKey.getAndIncrement());
statement.setString(2, pnsVideo.getTitle());
statement.setString(3, Joiner.on(",").join(pnsVideo.getTags()));
statement.setString(4, Joiner.on(",").join(pnsVideo.getActors()));
statement.execute();
} catch (final SQLException e) {
throw new FTSearchIndexException(e); // todo logging?!
}
}
Спасибо за любые предложения!