The intersection query doesn't have to be a global graph scan.
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> ids = [1,4,6]
==>1
==>4
==>6
gremlin> // union
gremlin> g.V(ids).both().dedup()
==>v[3]
==>v[2]
==>v[4]
==>v[5]
==>v[1]
gremlin> // intersection
gremlin> matchPatterns = ids.tail().collect {__.as("a").both().hasId(it)}.toArray() as Traversal[]
==>[StartStep@[a], VertexStep(BOTH,vertex), HasStep([~id.eq(4)])]
==>[StartStep@[a], VertexStep(BOTH,vertex), HasStep([~id.eq(6)])]
gremlin> g.V(ids.head()).both().dedup().match(matchPatterns).select("a")
==>v[3]