Janusgraph: Document replacement for deprecated StandardJanusGraphTx#multiQuery() method

Created on 2 Apr 2018  路  23Comments  路  Source: JanusGraph/janusgraph

See this thread for details:

As remarked earlier here, my guess is that the MultiQuery API is deprecated because of replacement by:

https://static.javadoc.io/org.janusgraph/janusgraph-core/0.2.0/org/janusgraph/graphdb/query/vertex/MultiVertexCentricQueryBuilder.html

It would be useful, though, to have:

  • a section in the JanusGraph ref docs about the MultiVertexCentricQuery
  • some pointers in the deprecated API towards the new one
aredocs kincleanup

Most helpful comment

I'll aim to add some tests and create a PR later this week.

In addition, unless anyone objects, in that PR I'll also remove the Deprecated annotation from the interface in Transaction.java. Because even without this additional change the multiQuery() method is fundamental to the use of the query.batch setting and removing the Deprecated annotation will allow this issue to be closed.

All 23 comments

I can only guess what drove the deprecation decision originally, but my bet is that it had something to do with deprecating it for external use. Historically, prior to Titan 1.0, the only way to parallelize communication with the storage layer was via direct use of the Titan multiquery calls. Gremlin traversals would not make use of them and you were limited to lazy loading from the storage layer unless you used this API directly. Titan 1.0 came with TinkerPop 3 support which in turn gave the graph providers the ability to apply their own optimization strategies to Gremlin traversals. With this, Titan 1.0 came with a query.batch setting that lives on, to this day, in Janus. If you flip that on, Gremlin traversals will use multiquery behind the scenes and you'll see the benefits of reduced latencies. So, long story short, multiquery is currently used and internally, and we'll be into the foreseeable future. I believe the deprecation was probably meant more as a marker to outside consumers not to use this API directly, and to instead stick accessing it indirectly, through Gremlin. The documentation used to contain a section on using multiquery, but it was removed.

At this point, I'm tempted to remove deprecation because it seems inconsistent with how the rest of the "internal" Janus API is treated. Technically a user could use the other methods we expose, like the regular old query, but I'd never recommend they do that, and those other methods are not deprecated. I think the docs could benefit from a more opinionated section near the beginning driving users towards using the Gremlin process API and steering them away from the TinkerPop structure API (graph.addVertex, graph.addEdge, etc.) and the Janus APIs (query, multiquery, etc.).

After reading the thread mentioned in the description of this issue, I used a similar approach to speed up a gremlin query against a simple hub and spoke graph and a Cassandra storage backend. There were 1000 spoke edges and at the end of each a vertex with a unique name. I鈥檇 found the following query to be slow, taking several seconds to execute.

Vertex rim999 = g.traversal().V(hub).outE("spoke").inV().has("name", "rim_999").next();

Yet when I preceded the query with the following call to multiQuery to pre-fetch the properties

g.multiQuery().addAllVertices(g.traversal().V(hub).outE("spoke").inV().next(1000)).properties();

It was significantly faster returning in under a second I think this was because the vertex properties were pre-loaded into the cache by the multiQuery. After reading that the query.batch setting was using multiQuery under the covers I enabled it hoping I could remove the explicit call to multiQuery. However, when I did so the query times went back up to seconds. So setting query.batch=true for this style of query appears to make no difference to the execution times.

I鈥檝e since done some analysis of what鈥檚 going on and found that with query.batch enabled JanusGraph does indeed use multiQuery, but only on the V(hub).outE("spoke") part of the query. This means it quickly returns all 1000 spoke edges and then feeds them individually into the inV().has("name", "rim_999") part of the query which then does a separate round trip to the storage backend to retrieve the properties for each vertex. So, it appears that despite getting the edges in one network trip we have to make 1000 additional network trips to get each vertex name property.

I then looked into how we might use multiQuery to optimise the inV().has("name", "rim_999") part of the query and eliminate those extra calls to the storage backend. By extending the EdgeVertexStep class I was able to use multiQuery to implicitly pre-fetch the properties in a similar way to the example above and bring the query times back down to what they had been with the explicit call.

@twilmes @pluradj I鈥檝e pushed up the changes I made onto a private branch so you can see what I did. Do you think it is worth taking this further? An if so, do you have any pointers to how I might write some performance tests to go along with the changes.

then feeds them individually into the inV().has("name", "rim_999") part of the query which then does a separate round trip to the storage backend to retrieve the properties for each vertex

Isn't it sufficient to enable query.fast-property to prevent additional backend queries to retrieve the properties for the has step?

I just tried such a traversal on our graph and it seemed as if out('edgeLabel') (or out('edgeLabel')) already returned all neighbours with their properties so the subsequent has() step could filter them in-memory.
Here is the profile()-output for such a traversal:

gremlin> g.V(12345678901).outE('ConnectedToIPAddress').inV().has('IP', '12.34.5.6').profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[12345678901])                                        1           1           2.634     0.02
JanusGraphVertexStep(OUT,[ConnectedToIPAddress]...                 16384       16384         180.971     1.25
    \_condition=type[ConnectedToIPAddress]
    \_isFitted=true
    \_vertices=1
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b3b75075
    \_orders=[]
    \_isOrdered=true
  optimization                                                                                 0.038
  backend-query                                                    16384                      89.974
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b3b75075
HasStep([IP.eq(12.34.5.6)])                                            1           1       14280.879    98.73
                                            >TOTAL                     -           -       14464.486        -

Or did you mean that out().has() could be executed together in a single backend call that only returns neighbours that pass the filter condition of the has step? That would be definitely an interesting improvement, considering that JanusGraph had to retrieve 16k neighbours here and then filter them in-memory.

@FlorianHockmann you asked

Isn't it sufficient to enable query.fast-property to prevent additional backend queries to retrieve the properties for the has step

And the answer is not quite, because as far as I can see the outE() part of the query returns only the ID of the vertex and not its properties. It's not until you ask for any property of the vertex with has that query.fast-property will kick in and return them all so if you then later ask for a different property it'll be cached and won't require a new request to the storage backend.

That said your query does look like it would benefit from the optimisation I'm suggesting. I tried the following on a similar topology with some 8K interfaces and janusGraph 0.3.0.

gremlin> g.V(661800).outE('aggregation').inV().has('uniqueId', 'banana').profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[661800])                                             1           1          38.993     0.20
JanusGraphVertexStep(OUT,[aggregation],vertex)                      8847        8847         269.512     1.40
    \_condition=type[aggregation]
    \_isFitted=true
    \_vertices=1
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bcaf2b
    \_orders=[]
    \_isOrdered=true
  optimization                                                                                76.221
  backend-query                                                     8847                      59.859
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bcaf2b
HasStep([uniqueId.eq(banana)])                                                             18995.774    98.40
                                            >TOTAL                     -           -       19304.281        -

There were no interfaces called banana so, as expected, the above query retuned nothing. But what it did do is pull all the properties of those 8K interfaces into the cache in a similar way to the mulitQuery optimisation I'm proposing. So, if I immediately follow the above with a second query to return interface interface8831 it's now much faster:

gremlin> g.V(661800).outE('aggregation').inV().has('uniqueId', 'interface8831').profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[661800])                                             1           1           0.127     0.21
JanusGraphVertexStep(OUT,[aggregation],vertex)                      8847        8847           8.948    14.50
    \_condition=type[aggregation]
    \_isFitted=true
    \_vertices=1
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bcaf2b
    \_orders=[]
    \_isOrdered=true
  optimization                                                                                 0.167
HasStep([uniqueId.eq(interface8831)])                                  1           1          52.622    85.29
                                            >TOTAL                     -           -          61.698        -

The first query took 19,304.281 milliseconds and I think much of that was some 8K trips to the storage back end to individually fetch vertex's properties. The second query didn't need to make those 8K trips as those properties were now cached in memory and so was significantly faster at just 61.698 milliseconds.

Is a second gremlin query against your graph much faster than the first?

I also tried running the above query with a build on my branch with the extra multiQuery to prefetch the properties in place and found that it didn't quite work for JanusGraph version 0.3.0 (I'd previously only tested on the 0.2.0 branch). But after tweaking things a bit I was able to get the following:

gremlin> g.V(661800).outE('aggregation').inV().has('uniqueId', 'interface8831').profile()
JanusGraphVertexStep: Using multiQuery to pre-fetch properties for 8847 vertices
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[661800])                                             1           1          37.995     1.62
JanusGraphVertexStep(OUT,[aggregation],vertex)                      8847        8847        2008.909    85.46
    \_condition=type[aggregation]
    \_isFitted=true
    \_vertices=1
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bcaf2b
    \_orders=[]
    \_isOrdered=true
    \_multi=true
  optimization                                                                                80.931
  backend-query                                                     8847                      63.655
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bcaf2b
HasStep([uniqueId.eq(interface8831)])                                  1           1         303.910    12.93
                                            >TOTAL                     -           -        2350.815        -

The extra line is some debug I added to check it was calling multiQuery. So, for this data set the optimisation brings the query time down from 19,304.281 milliseconds to just 2,350.815 milliseconds. I'll tidy up the code over the next few days and and push up a change to make this work with version 0.3.0 so people can see what I've done.

Have merged the updated changes which brought the query time down from 19 seconds to just over 2 seconds to this private branch.

Is a second gremlin query against your graph much faster than the first?

Yes, you're right, it gets a lot faster for the 2nd and 3rd time. It seems to be really just caching at play here.
I was just irritated by the profile() output as I expected to see 2 different backend-queries there, one to fetch the neighbours (or their ids) and another to evaluate the has-step for them.

Your suggestion sounds like a great idea to me and I also just skimmed over your changes and they look good. So, it would be good if you could create a PR for that, ideally even with some kind of testing (I haven't really yet looked into how these optimizations can be tested in JanusGraph).

I'll aim to add some tests and create a PR later this week.

In addition, unless anyone objects, in that PR I'll also remove the Deprecated annotation from the interface in Transaction.java. Because even without this additional change the multiQuery() method is fundamental to the use of the query.batch setting and removing the Deprecated annotation will allow this issue to be closed.

Looks like this issue is done now that the API is not deprecated any more (#1460) and because users shouldn't directly use this API in the first place we don't need any docs on it, right?

@FlorianHockmann if you recall we decided that it would be unwise to use the new batch-property-prefetch optimisation if a limit was applied, because the traversal was not interested in the entire results set, and we don鈥檛 want it to load many 1000s of unnecessary properties.

It was a this post, I think from @porunov, where he called .next(50000) which originally gave me the idea for this optimisation:

List<Vertex> locations = graph.traversal().V().hasLabel("location").has("location_type", 3).next(50000);
graph.multiQuery().addAllVertices(locations).properties();
Integer myId = locations.get(123).<Integer>value("location_id"); // Properties are returned immediately without network calls.

I recently found myself having to do something very similar for some application code that was paging through a large number of vertices connected to a super node. The reason being that because of the limit the batch-property-prefetch optimisation couldn't be used. So, as above, I explicitly called multiQuery in the application code to preload the properties in the results set before looking at them.

So, I think there are some edges cases, such as paging, where users may still wish to call this API directly. So perhaps we should add something to the documentation or add some javadoc?

Could we let users activate this optimization on a per-traversal basis by exposing it with a traversal strategy? It would be really great if we wouldn't have to rely on anything outside of the traversal API for users to call.

That's a nice idea, I think there's probably something we can do there to avoid the explicit call to multiQuery I gave in my previous comment.

@FlorianHockmann It has also occurred to me that the example I gave in comment https://github.com/JanusGraph/janusgraph/issues/984#issuecomment-488277486 the explicit call to multiQuery:

graph.multiQuery().addAllVertices(locations).properties();

Could be replaced with an implicit one:

graph.traversal().V(locations).properties().next(limit);

Which if query.batch was enabled would do the same thing, so when you said:

Looks like this issue is done now that the API is not deprecated any more (#1460) and because users shouldn't directly use this API in the first place we don't need any docs on it, right?

I think the answer is yes, users shouldn't directly use this API in the first place and we don't need docs on it, so this issue can probably be closed.

Good to hear, then I'll close this now.

Hi @FlorianHockmann,
I am very new to Janusgraph and graphs in general, I was encountering the same issue and downloaded the latest 0.4.0, I have following questions, any help/guidance would be appreciated.

  1. we are trying to use janusgraph to store wikidata entities.
  2. this query was was giving me the same issue mentioned g.V().has('qid','Q33999').inE('P106').otherV().outE('P2139').count().toList()
  3. the above query was timing out because otherV returns 189285 results and it tries to back that many times to fetch an edge P2139.
  4. we used version 0.4.0 and configured the following: batch-property-prefetch=true
  5. the above does not set the batchPropertyPrefetching=true in flatMap.java
  6. for now i hardcoded this to see how this will affect my results but it seems that it is not behaving as i believe it is supposed to.
  7. flatMap.flatMap(...) gets called 10,000s of times and vertices size is 0 in all the calls except the first one where is it 20,000.

please let me know if my understanding of the issue is correct and if this solution is trying to address it, if so what am I am doing wrong? any other suggestions with my problem would be helpful, in terms of how we can index/query the data to get better/faster results.

Thanks in advance!

Z

@smcquillan Do you have any idea what could be the issue here?

@ziakhan I took a look at this using a similar query against the example graph of the gods :

g.V().has('name','jupiter').inE('father').otherV().outE('battled').count().profile()

For this query we'd not expect the batch-property-prefetch=true optimisation to kick in because the query is just returning edges it's not filtering on any vertex properties at the far end of those edges. However, you might find that the query.batch=true optimisation could help. Here's an example of the profiling data with that enabled:

gremlin> g.V().has('name','jupiter').inE('father').otherV().outE('battled').count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
JanusGraphStep([],[name.eq(jupiter)])                                  1           1           0.562    43.46
    \_condition=(name = jupiter)
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=multiKSQ[1]@2147483647
    \_index=name
  optimization                                                                                 0.022
  optimization                                                                                 0.183
JanusGraphVertexStep(IN,[father],vertex)                               1           1           0.311    24.10
    \_condition=type[father]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81b61911
    \_multi=true
    \_vertices=1
  optimization                                                                                 0.090
JanusGraphVertexStep(OUT,[battled],edge)                               3           3           0.277    21.47
    \_condition=type[battled]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81b55e55
    \_multi=true
    \_vertices=1
  optimization                                                                                 0.075
CountGlobalStep                                                        1           1           0.141    10.97
                                            >TOTAL                     -           -           1.293        -

Note the profile contains \_multi=true meaning that the query.batch optimisation has been applied.

Thank you @florianhockmann and @smcquillan for the response, I understand what you are saying and will try to turn on the query.batch=true and see how it impacts the performance. I was under the impression that it was already turned on.

Also, I was working with another query simultaneously, which will probably benefit from the above changes but decided to use the above query for the post. Now I know the difference, Here is the other query: g.V().has("qid", 'Q76').outE().otherV().hasNot("qid").profile()

I really appreciate your prompt response and would like your help in understanding the response from the profile() command which i was able to run with the query.batch=true Can you guide me to some documentation that i can reference or would you be able to explain to me what's happening in each step and how many round trips are made to the storage backend? and is there a way to optimize this query?

gremlin> g.V().has('qid','Q33999').inE('P106').otherV().outE('P2139').path().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
JanusGraphStep([],[qid.eq(Q33999)])                                    2           2         109.895     0.09
    \_condition=(qid = Q33999)
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=multiKSQ[1]@2147483647
    \_index=IndexUniqueqid
  optimization                                                                                 3.534
  optimization                                                                                64.090
  backend-query                                                        2                      13.077
    \_query=IndexUniqueqid:multiKSQ[1]@2147483647
JanusGraphVertexStep(IN,[P106],edge)                              190309      190309        1419.247     1.16
    \_condition=type[P106]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b3d0a13d
    \_multi=true
    \_vertices=2
  optimization                                                                                 9.236
  backend-query                                                   190309                     707.031
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b3d0a13d
EdgeOtherVertexStep                                               190309      190309         421.546     0.34
JanusGraphVertexStep(OUT,[P2139],edge)                                 1           1      120500.930    98.41
    \_condition=type[P2139]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b38d7533
    \_multi=true
    \_vertices=190301
  optimization                                                                                12.160
  backend-query                                                        1                  119489.347
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@b38d7533
PathStep                                                               1           1           1.926     0.00
                                            >TOTAL                     -           -      122453.547        -

Thanks in advance!

@ziakhan I did a little testing of my own with similar queries on a vertex with some 30,000 edges and a Cassandra database as the back end. One thing I did note is that, as I expected, using .hasNot doesn't not trigger the prefetching of the properties. I also noted in your system you have a very large number of edges, much more than the default size of the maximum size of the transaction-level cache of recently-used vertices, which is 20,000.

Using .has('name', neq('bob')) to trigger the batch property pre-fetching I got the following profile with the default cache size of 20,000:

gremlin> g.V(6554048).outE('aggregation').otherV().has('name', neq('bob')).count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[6554048])                                            1           1          35.538     0.15
JanusGraphVertexStep(OUT,[aggregation],vertex)                     30159       30159        2220.394     9.28
    \_condition=(PROPERTY AND visibility:normal)
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@8019d62e
    \_multi=true
    \_vertices=20000
    \_multiPreFetch=true
  optimization                                                                                82.480
  backend-query                                                    30159                     275.560
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bebe6b
  optimization                                                                                 0.712
  backend-query                                                   257398                    1491.029
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@8019d62e
HasStep([name.neq(bob)])                                           28054       28054       21612.923    90.33
CountGlobalStep                                                        1           1          56.938     0.24
                                            >TOTAL                     -           -       23925.795        -

Note the \_multiPreFetch=true in the profile data which is showing that the optimisation kicked in. However, when I increased the value of cache.tx-cache-size to 30,000 so all the vertices could fit into the cache it was much faster.

gremlin> g.V(6554048).outE('aggregation').otherV().has('name', neq('bob')).count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[6554048])                                            1           1          34.902     1.11
JanusGraphVertexStep(OUT,[aggregation],vertex)                     30159       30159        2533.292    80.31
    \_condition=(PROPERTY AND visibility:normal)
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@8019d62e
    \_multi=true
    \_vertices=30159
    \_multiPreFetch=true
  optimization                                                                                77.912
  backend-query                                                    30159                     181.886
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bebe6b
  optimization                                                                                 0.584
  backend-query                                                   387857                    1989.596
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@8019d62e
HasStep([name.neq(bob)])                                           28054       28054         561.693    17.81
CountGlobalStep                                                        1           1          24.537     0.78
                                            >TOTAL                     -           -        3154.426        -

Finally for reference with query.batch-property-prefetch=false it took longer than either of the above:

gremlin> g.V(6554048).outE('aggregation').otherV().has('name', neq('bob')).count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphStep(vertex,[6554048])                                            1           1          41.218     0.06
JanusGraphVertexStep(OUT,[aggregation],vertex)                     30159       30159         634.747     0.91
    \_condition=type[aggregation]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bebe6b
    \_multi=true
    \_vertices=1
  optimization                                                                                83.462
  backend-query                                                    30159                     204.227
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81bebe6b
HasStep([name.neq(bob)])                                           28054       28054       69114.934    98.84
CountGlobalStep                                                        1           1         131.663     0.19
                                            >TOTAL                     -           -       69922.564        -

@smcquillan once again, i really appreciate your effort in helping me with this, it is indeed very very helpful and now i understand that two queries that i posted are indeed different and can benefit from different optimizations (i initially thought them to be similar). Below is my response and possibly a few more question:

query 1:
g.V().has("qid", 'Q76').outE().otherV().hasNot("qid")
we plan to use this for frequently updating all the changes that are made to entities on wikidata and there will never be more than a few hundred edges, the suggestions with using has instead of hasNot certainly helped bhut for this particular scenario we will not need to increase the value of cache.tx-cache-size

query2: g.V().has('qid','Q33999').inE('P106').otherV().outE('P2218').order().by('amount',decr).limit(1).path().by(valueMap()).toList()

  • this query we are trying to find actor(Q33999) with highest 'net worth'(P2218), P106 is profession
  • the problem is that otherV has 190309 vertices and in order to get the P2218 it has to traverse 190309 edges. We were thinking of storing the value for P2218 as a property on the Vertex and i believe we can benefit from using has and query.batch-property-prefetch=true
  • currently this command never returns and we are setting a timeout
  • any help with this would be appreciated and if there is anything better we can do to get the max value other than sorting?

thanks again and wish you have a great weekend!

@ziakhan the cost here is in the fact that you are sorting and ordering the results, which means that looking at all 190309 edges is unavoidable. I'd suggest you investigate the use of a vertex centred index on the amount property. If this index were ordered in descending order then you may be able avoid needing to look at the rest of the edges when the sort is applied.

I have a new question. When I test on my dataset I find if the eage has alias name use AS can not trigger _multiPreFetch optimization

no eage alias trigger _multiPreFetch

g.V().has("MOBILE", "name", P.within('186xxxx6666','134xxxx3910')) \
               .bothE("CALL").otherV().has('is_register','true').as('m2').profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
JanusGraphStep([],[~label.eq(MOBILE), name.with...                     2           2          12.928    46.34
    \_condition=(~label = MOBILE AND (name = 18658606666 OR name = 13428023910))
    \_orders=[]
    \_isFitted=false
    \_isOrdered=true
    \_query=multiKSQ[2]@2147483647
    \_index=name
  optimization                                                                                 0.007
  optimization                                                                                 0.077
  backend-query                                                        2                      12.671
    \_query=name:multiKSQ[2]@2147483647
JanusGraphVertexStep(BOTH,[CALL],vertex)                             845         845           3.582    12.84
    \_condition=(PROPERTY AND visibility:normal)
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@8019d62e
    \_multi=true
    \_vertices=46
    \_multiPreFetch=true
  optimization                                                                                 0.029
  optimization                                                                                 0.001
  optimization                                                                                 0.001
HasStep([is_register.eq(true)])@[m2]                                 170         170          11.389    40.82
                                            >TOTAL                     -           -          27.900        -

has eage alias can not trigger _multiPreFetch

g.V().has("MOBILE", "name", P.within('186xxxx6666','134xxxx3910')) \
    .bothE("CALL").as("r").otherV().has('is_register','true').as('m2').profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
JanusGraphStep([],[~label.eq(MOBILE), name.with...                     2           2           0.455     2.98
    \_condition=(~label = MOBILE AND (name = 18658606666 OR name = 13428023910))
    \_orders=[]
    \_isFitted=false
    \_isOrdered=true
    \_query=multiKSQ[2]@2147483647
    \_index=name
  optimization                                                                                 0.009
  optimization                                                                                 0.080
JanusGraphVertexStep(BOTH,[CALL],edge)@[r]                           845         845           2.856    18.68
    \_condition=type[CALL]
    \_orders=[]
    \_isFitted=true
    \_isOrdered=true
    \_query=org.janusgraph.diskstorage.keycolumnvalue.SliceQuery@81b6b2fe
    \_multi=true
    \_vertices=2
  optimization                                                                                 0.024
EdgeOtherVertexStep                                                  845         845           1.162     7.60
HasStep([is_register.eq(true)])@[m2]                                 170         170          10.822    70.75
                                            >TOTAL                     -           -          15.297        -

@smcquillan can you help?

@blacklovebear I also encounter the same issue. This is my query:
g.V().has("A", "xxx").inE("Linking").outV().as("a").out().as("b").properties().path().by("B").by("C").from("a").to("b").profile()

It results in a sequence of getSlice() instead of using getSlices() that should be triggered by enabling multi-key query.

Without using alias, I don't know how to write a similar query. Any help?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amcp picture amcp  路  5Comments

jerryjch picture jerryjch  路  3Comments

pluradj picture pluradj  路  4Comments

chrislbs picture chrislbs  路  3Comments

porunov picture porunov  路  4Comments