Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize match node label #5176

Merged
merged 1 commit into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 28 additions & 40 deletions src/graph/executor/query/TraverseExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ Status TraverseExecutor::buildRequestVids() {
auto iter = static_cast<SequentialIter*>(inputIter);
size_t iterSize = iter->size();
vids_.reserve(iterSize);
initVids_.reserve(iterSize);
auto* src = traverse_->src();
QueryExpressionContext ctx(ectx_);

Expand All @@ -56,11 +55,9 @@ Status TraverseExecutor::buildRequestVids() {
}
if (uniqueVid.emplace(vid).second) {
vids_.emplace_back(vid);
initVids_.emplace_back(vid);
}
}
} else {
initVids_.reserve(iterSize);
const auto& spaceInfo = qctx()->rctx()->session()->space();
const auto& metaVidType = *(spaceInfo.spaceDesc.vid_type_ref());
auto vidType = SchemaUtil::propTypeToValueType(metaVidType.get_type());
Expand All @@ -71,7 +68,6 @@ Status TraverseExecutor::buildRequestVids() {
continue;
}
vids_.emplace_back(vid);
initVids_.emplace_back(vid);
}
}
return Status::OK();
Expand Down Expand Up @@ -164,27 +160,18 @@ folly::Future<Status> TraverseExecutor::handleResponse(RpcResponse&& resps) {
auto listVal = std::make_shared<Value>(std::move(list));
auto iter = std::make_unique<GetNeighborsIter>(listVal);
if (currentStep_ == 1) {
if (range_ && range_->min() == 0) {
result_.rows = buildZeroStepPath(iter.get());
}
// match (v)-[e:Rel]-(v1:Label1)-[e1*2]->() where id(v0) in [6, 23] return v1
// the attributes of v1 will be obtained in the second traverse operator
// If the conditions are not met, the path in the previous step needs to be filtered out
std::unordered_set<Value, VertexHash, VertexEqual> existVids;
existVids.reserve(iter->numRows());
initVertices_.reserve(iter->numRows());
auto vertices = iter->getVertices();
// match (v)-[e:Rel]-(v1:Label1)-[e1*2]->() where id(v0) in [6, 23] return v1
// save the vertex that meets the filter conditions as the starting vertex of the current
// traverse
for (auto& vertex : vertices.values) {
if (vertex.isVertex()) {
existVids.emplace(vertex);
initVertices_.emplace_back(vertex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it necessary to deduplicate the vids for next traverse ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first column vid in the result returned by getNeighbor is not repeated

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense.

}
}
auto initVidIter = initVids_.begin();
while (initVidIter != initVids_.end()) {
if (existVids.find(*initVidIter) == existVids.end()) {
initVidIter = initVids_.erase(initVidIter);
} else {
initVidIter++;
}
if (range_ && range_->min() == 0) {
result_.rows = buildZeroStepPath();
}
}
expand(iter.get());
Expand Down Expand Up @@ -248,15 +235,14 @@ void TraverseExecutor::expand(GetNeighborsIter* iter) {
}
}

std::vector<Row> TraverseExecutor::buildZeroStepPath(GetNeighborsIter* iter) {
if (!iter || iter->numRows() == 0) {
std::vector<Row> TraverseExecutor::buildZeroStepPath() {
if (initVertices_.empty()) {
return std::vector<Row>();
}
std::vector<Row> result;
result.reserve(iter->size());
auto vertices = iter->getVertices();
result.reserve(initVertices_.size());
if (traverse_->trackPrevPath()) {
for (auto& vertex : vertices.values) {
for (auto& vertex : initVertices_) {
auto dstIter = dst2PathsMap_.find(vertex);
if (dstIter == dst2PathsMap_.end()) {
continue;
Expand All @@ -272,7 +258,7 @@ std::vector<Row> TraverseExecutor::buildZeroStepPath(GetNeighborsIter* iter) {
}
}
} else {
for (auto& vertex : vertices.values) {
for (auto& vertex : initVertices_) {
Row row;
List edgeList;
edgeList.values.emplace_back(vertex);
Expand All @@ -297,8 +283,8 @@ folly::Future<Status> TraverseExecutor::buildResult() {
return finish(ResultBuilder().value(Value(std::move(result_))).build());
}
if (FLAGS_max_job_size <= 1) {
for (const auto& vid : initVids_) {
auto paths = buildPath(vid, minStep, maxStep);
for (const auto& initVertex : initVertices_) {
auto paths = buildPath(initVertex, minStep, maxStep);
if (paths.empty()) {
continue;
}
Expand All @@ -312,22 +298,22 @@ folly::Future<Status> TraverseExecutor::buildResult() {
}

folly::Future<Status> TraverseExecutor::buildPathMultiJobs(size_t minStep, size_t maxStep) {
DataSet vids;
vids.rows.reserve(initVids_.size());
for (auto& vid : initVids_) {
DataSet vertices;
vertices.rows.reserve(initVertices_.size());
for (auto& initVertex : initVertices_) {
Row row;
row.values.emplace_back(std::move(vid));
vids.rows.emplace_back(std::move(row));
row.values.emplace_back(std::move(initVertex));
vertices.rows.emplace_back(std::move(row));
}
auto val = std::make_shared<Value>(std::move(vids));
auto val = std::make_shared<Value>(std::move(vertices));
auto iter = std::make_unique<SequentialIter>(val);

auto scatter = [this, minStep, maxStep](
size_t begin, size_t end, Iterator* tmpIter) mutable -> std::vector<Row> {
std::vector<Row> rows;
for (; tmpIter->valid() && begin++ < end; tmpIter->next()) {
auto& vid = tmpIter->getColumn(0);
auto paths = buildPath(vid, minStep, maxStep);
auto& initVertex = tmpIter->getColumn(0);
auto paths = buildPath(initVertex, minStep, maxStep);
if (paths.empty()) {
continue;
}
Expand Down Expand Up @@ -355,8 +341,10 @@ folly::Future<Status> TraverseExecutor::buildPathMultiJobs(size_t minStep, size_
}

// build path based on BFS through adjancency list
std::vector<Row> TraverseExecutor::buildPath(const Value& vid, size_t minStep, size_t maxStep) {
auto vidIter = adjList_.find(vid);
std::vector<Row> TraverseExecutor::buildPath(const Value& initVertex,
size_t minStep,
size_t maxStep) {
auto vidIter = adjList_.find(initVertex);
if (vidIter == adjList_.end()) {
return std::vector<Row>();
}
Expand All @@ -380,7 +368,7 @@ std::vector<Row> TraverseExecutor::buildPath(const Value& vid, size_t minStep, s
if (maxStep == 1) {
if (traverse_->trackPrevPath()) {
std::vector<Row> newResult;
auto dstIter = dst2PathsMap_.find(vid);
auto dstIter = dst2PathsMap_.find(initVertex);
if (dstIter == dst2PathsMap_.end()) {
return std::vector<Row>();
}
Expand Down Expand Up @@ -461,7 +449,7 @@ std::vector<Row> TraverseExecutor::buildPath(const Value& vid, size_t minStep, s
}
if (traverse_->trackPrevPath()) {
std::vector<Row> newPaths;
auto dstIter = dst2PathsMap_.find(vid);
auto dstIter = dst2PathsMap_.find(initVertex);
if (dstIter != dst2PathsMap_.end()) {
auto& prevPaths = dstIter->second;
for (auto& prevPath : prevPaths) {
Expand Down
6 changes: 3 additions & 3 deletions src/graph/executor/query/TraverseExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class TraverseExecutor final : public StorageAccessExecutor {

folly::Future<Status> buildResult();

std::vector<Row> buildPath(const Value& vid, size_t minStep, size_t maxStep);
std::vector<Row> buildPath(const Value& initVertex, size_t minStep, size_t maxStep);

folly::Future<Status> buildPathMultiJobs(size_t minStep, size_t maxStep);

Expand All @@ -77,7 +77,7 @@ class TraverseExecutor final : public StorageAccessExecutor {

bool hasSameEdge(const std::vector<Value>& edgeList, const Edge& edge);

std::vector<Row> buildZeroStepPath(GetNeighborsIter* iter);
std::vector<Row> buildZeroStepPath();

Expression* selectFilter();

Expand Down Expand Up @@ -127,7 +127,7 @@ class TraverseExecutor final : public StorageAccessExecutor {
ObjectPool objPool_;

std::vector<Value> vids_;
std::vector<Value> initVids_;
std::vector<Value> initVertices_;
DataSet result_;
// Key : vertex Value : adjacent edges
std::unordered_map<Value, std::vector<Value>, VertexHash, VertexEqual> adjList_;
Expand Down