Выполнить запрос лениво в Orient-DB

В текущем проекте нам нужно найти самые дешевые пути в почти полностью связанном графе, который может содержать множество ребер на пару вершин.

Мы разработали плагин, содержащий функции

  1. для специального обхода этого графа, чтобы снизить повторяемость аналогичных путей, в то время как TRAVERSE выполнение. Мы будем ссылаться на это как search()
  2. для особого эффективного извлечения искомой информации из результатов таких обходов. Мы будем ссылаться на это как extract()
  3. для извлечения лучших N записи по целевому параметру без затрат ORDER BY, Мы будем ссылаться на это как best()

Но полученный запрос все еще имеет неудовлетворительную производительность для полных данных.

Поэтому мы решили изменить search() функция, так что он может смотреть лучшие края в первую очередь и обрезать пути, ведущие к определенно нежелательным результатам, используя текущее состояние best() функция.
Общее решение - это гибкая реализация метода Branch and Bound

Результирующий запрос (опущен extract() шаг) должен выглядеть

SELECT best(path, <limit>) FROM (
   TRAVERSE search(<params>) FROM #<starting_point>
   WHILE <conditions on intermediate vertixes>
  ) WHERE <conditions on result elements> 

Эта форма очень желательна, чтобы мы могли адаптировать условия под WHILE а также WHERE для нашей текущей задачи. path поле генерируется search() содержащий всю информацию для best() продолжать.

Беда в том, что best() функция выполняется строго после search() функция, так search() не может обрезать неоптимальные ветви по результатам, уже оцененным best(),

Итак, вопрос таков:
Есть ли способ передать результаты из TRAVERSE шаг к SELECT шаг в том, что старые пути были TRAVERSEд с search() после более ранних путей, обработанных SELECT с best()?

1 ответ

Решение

Выполнение запроса в этом случае будет потоковым. Если вы добавите

 System.out.println()

или если вы установите точку останова в своих функциях, вы увидите, что последовательность вызовов будет

search
best
search
best
search
...

Вы можете использовать объект ThreadLocal http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html

чтобы сохранить некоторые контекстные данные и поделиться ими между двумя функциями, или вы можете использовать OCommandContext (последний параметр в OSQLFunction.execute() метод хранения контекстной информации.

Ты можешь использовать context.getVariable() а также context.setVariable() за это.

Контексты двух запросов (родительский и внутренний запрос) различны, но они должны быть связаны отношениями родитель / потомок, так что вы сможете получить их, используя OCommandContext.getParent()

Другие вопросы по тегам