Выполнить запрос лениво в Orient-DB
В текущем проекте нам нужно найти самые дешевые пути в почти полностью связанном графе, который может содержать множество ребер на пару вершин.
Мы разработали плагин, содержащий функции
- для специального обхода этого графа, чтобы снизить повторяемость аналогичных путей, в то время как
TRAVERSE
выполнение. Мы будем ссылаться на это какsearch()
- для особого эффективного извлечения искомой информации из результатов таких обходов. Мы будем ссылаться на это как
extract()
- для извлечения лучших
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()