Статьи

Сравнение эффективности поиска CQEngine со стандартными коллекциями Java

В предыдущем посте мы рассмотрели, как использовать CQEngine для запроса коллекции Java. Мы выполнили три довольно упрощенных запроса: поиск равных , окончание  поиском и их комбинацию. В этом посте мы увидим, насколько быстро CQEngine сравнивается с итерацией по коллекции, а также с увеличением времени поиска по мере увеличения размера коллекции.

1. Равный Поиск

Код для поиска равных в индексированной коллекции с использованием CQEngine приведен ниже. Здесь был использован хэш-индекс. Для полного кода, посетите оригинальный  пост .

public void indexedSearchForEquals(String search) throws Exception {
    Query<User> query = equal(User.FULL_NAME, search);
    for (User user : indexedUsers.retrieve(query)) {
	// System.out.println(user.getFullname());
    }
}

Эквивалентный код для повторного выполнения одного и того же поиска:

public void searchIterativelyForEquals(String search) throws Exception {
     for (User user : users) {
       if (user.getFullname().equals(search)) {
          // System.out.println(user.getFullname());
       }
     }
}

cqengine stats

Вы заметите, что итеративный поиск растет линейно, тогда как индексированный поиск CQEngine остается почти постоянным. Для миллиона предметов разница в производительности значительна. Следует отметить, что это только время поиска, и оно не включает время для построения самого индекса, что для миллиона объектов может быть существенным.

2. Заканчивается поиском

Код для выполнения индексированного поиска на основе CQEngine для поиска объекта с атрибутом, заканчивающимся определенным суффиксом, приведен ниже. Индекс дерева суффиксов используется для этого поиска. Опять же, вы можете найти полный пост здесь .

public void indexedSearchForEndsWith(String suffix) throws Exception {
	Query query = endsWith(User.FULL_NAME, suffix);
	for (User user : indexedUsers.retrieve(query)) {
		// System.out.println(user.getFullname());
	}
}

Эквивалентный код для повторного выполнения одного и того же поиска:

public void searchIterativelyForEndsWith(String suffix) throws Exception {
	for (User user : users) {
		if (user.getFullname().endsWith(suffix)) {
			// System.out.println(user.getFullname());
		}
	}
}

cqengine stats

Для 10000 предметов на 100000 предметов, вы снова заметите, что шаблон тот же. Итеративный поиск растет линейно, тогда как индексированный поиск cqengine остается почти постоянным.

3.  Заканчивается на  или равно  поиску

В этом примере мы пытаемся найти элементы в коллекции, атрибут которых либо заканчивается определенной строкой, либо совпадает с другой строкой. Во-первых, индексированный поиск:

public void indexedSearchForEqualOrEndsWith(String equals, String endsWith) throws Exception {
	Query query = or(equal(User.FULL_NAME, equals),endsWith(User.FULL_NAME, endsWith));
		for (User user : indexedUsers.retrieve(query)) {
			// System.out.println(user.getFullname());
		}
}

Теперь итерационный код:

public void searchIterativelyForEqualsOrEndsWith(String equals, String endsWith) throws Exception {
      for (User user : users) {
	  if (user.getFullname().equals(equals)|| user.getFullname().endsWith(endsWith)) {
		// System.out.println(user.getFullname());
	  }
      }
}

cqengine stats

Для 10 000 пунктов на 100 000 пунктов шаблон остается прежним. Итеративные и индексированные результаты на этот раз занимают немного больше времени, но растут с той же скоростью, что и раньше.

CQEngine — отличная библиотека, которая позволяет запрашивать большие коллекции для получения желаемых результатов. Это может значительно повысить производительность вашего приложения за счет сокращения времени, необходимого для итераций, избегая попаданий в БД при запросе данных из БД, особенно если эти данные могут быть проиндексированы в памяти и не изменяются быстро и во многих других сценариях. Интересной идеей будет совместное использование Google Guava Cache и CQEngine для создания запрашиваемого кэша объектов для вашего приложения. Это для другого поста.