#gremlin #tinkerpop #tinkerpop3 #gremlin-server #amazon-neptune
#гремлин #tinkerpop #tinkerpop3 #gremlin-сервер #amazon-нептун
Вопрос:
В моем приложении есть функция поиска пользователей, в которой поисковик не хочет видеть некоторые результаты, он делает это, «блокируя» тег, при блокировке тега все пользователи, которые «подписаны» на этот тег, будут игнорироваться в его результатах поиска.
Я пишу запрос для фильтрации результатов поиска, и я нашел 2 способа получить то же самое:
Первый:
g.V(1991)
.out("blocked").fold().as("blockedTags")
.V().hasLabel("user")
.not(
where(
out("subscribed").where(
within("blockedTags")
)
)
)
Второй:
g.V(1991).as("user")
.V().hasLabel("user")
.not(
where(
out("subscribed")
.in("blocked")
.as("user")
)
)
Gremlify: https://gremlify.com/xnqhvtzo6b
Один использует within(), а другой выполняет 2 шага out() и in() , я хочу знать, какой из них быстрее, чтобы я мог решить, какой из них использовать, эти 2 варианта возможны во многих запросах моего приложения.
Редактировать:
Я запустил оба запроса в консоли gremlin с шагом profile () в конце, но >TOTAL
поле выдает случайные временные значения от 0,300 мс до 1,220 мс для обоих запросов, из-за этого я не знаю, как сравнить производительность 2 запросов.
Комментарии:
1. Хороший способ проанализировать такие вопросы — профилировать запросы. Вы пробовали отправлять запросы в конечную точку /status и замечали какие-либо различия?
2. Я еще не запускаю свой код на Neptune, я все еще разрабатываю с использованием gremlin-server на localhost. Я отредактировал вопрос с моим результатом после выполнения шага profile () в консоли gremlin
3. ХОРОШО, и я имел в виду /profile выше, а не /status
4. Я снова отредактировал свой вопрос, потому что после многократного выполнения profile() он выдает случайное время выполнения для обоих запросов
5. Судя по тегам в вопросе, похоже, что вы используете Amazon Neptune. В Neptune есть конечная точка /profile, к которой вы можете отправить запрос с помощью curl или из записных книжек Neptune (workbench). Это даст больше информации о том, как планировщик запросов обработал запрос. В общем, это хороший способ получить представление о том, как выполняется запрос.
Ответ №1:
Я предложу здесь общий ответ, который в значительной степени вытекает из комментариев к самому вопросу. Это действительно невозможно для profile()
одного графика, а затем спроецировать эти результаты на другой. У каждого из них будут разные возможности и характеристики производительности. Если вам нужно знать, какой из двух подходов к запросу лучше, тогда вы должны протестировать оба обхода в графовой системе, на которую вы собираетесь ориентироваться.
Я бы также опасался заходить слишком далеко в определенном направлении разработки, не проводя текущее тестирование на целевом графике. Точно так же, как вы не стали бы делать всю свою разработку на MySQL только для того, чтобы переключиться на Oracle, когда пришло время переходить к производству, вам действительно не следует пытаться построить все свое приложение на основе графика, который вы не собираетесь использовать. В этих системах есть небольшие различия, которые могут иметь для вас существенное значение.
Что касается различий во profile()
времени в TinkerGraph, в JVM обязательно должны быть временные различия, поскольку я предполагаю, что это тест на небольшом наборе данных, который находится в памяти. Или, возможно, для TinkerGraph нет существенной разницы между двумя подходами. Подумайте о попытке выполнить запросы несколько тысяч раз, усредните затраченное время и сравните это. Консоль Gremlin имеет clock()
функцию, которая помогает в этом. Конечно, как я упоминал ранее, что вы узнаете, нет никакой гарантии, что у вас есть правильное решение на Neptune.
Если вы хотите немного проанализировать свои запросы, я мог бы предложить несколько слов (хотя я не основываю это мышление конкретно на Neptune). То, как выполняется каждый из них, во многом зависит от вашей структуры графа, но я думаю, что я был бы первым запросом, который будет быстрее, потому что он захватывает «заблокированные» вершины с:
.out("blocked").fold()
и повторно используйте его снова и снова, сколько V().hasLabel('user')
бы их ни было. Хотя это просто внутреннее чувство. Я предполагаю, что список заблокированных будет относительно небольшим для одного пользователя, поэтому пройдите противоположный путь с:
out("subscribed").in("blocked")
было бы просто дороже, так как вам пришлось бы проходить гораздо больше «заблокированных» ребер, которые не заканчиваются начальной вершиной.