From cbf879e954d1dd0686090807eb238a4e7e501117 Mon Sep 17 00:00:00 2001 From: Sophie <84560950+Sophie-Xie@users.noreply.github.com> Date: Fri, 16 Jun 2023 16:30:16 +0800 Subject: [PATCH] cherry pick from nebula: Fix PushLimitDownFulltextIndexScanRule (#5601) (#2846) Fix PushLimitDownFulltextIndexScanRule (#5601) * Fix push limit down ft index scan rule * Fix limit offset bug in OptRule * Add plan tests Co-authored-by: Yee <2520865+yixinglu@users.noreply.github.com> --- .../PushLimitDownFulltextIndexScanRule2.cpp | 40 +++++++---- .../PushLimitDownFulltextIndexScanRule2.h | 15 ++-- .../fulltext_index/FulltextIndexScan.feature | 72 +++++++++++++++---- 3 files changed, 93 insertions(+), 34 deletions(-) diff --git a/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.cpp b/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.cpp index 72482519bbe..03cf519d309 100644 --- a/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.cpp +++ b/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.cpp @@ -18,6 +18,7 @@ using nebula::graph::FulltextIndexScan; using nebula::graph::HashInnerJoin; using nebula::graph::Limit; using nebula::graph::PlanNode; +using nebula::graph::Project; using nebula::graph::QueryContext; namespace nebula { @@ -38,9 +39,16 @@ const Pattern &PushLimitDownFulltextIndexScanRule2::pattern() const { PlanNode::Kind::kHashInnerJoin, { Pattern::create(PlanNode::Kind::kFulltextIndexScan), - Pattern::create({PlanNode::Kind::kGetVertices, PlanNode::Kind::kGetEdges}, + Pattern::create(PlanNode::Kind::kProject, { - Pattern::create(PlanNode::Kind::kArgument), + Pattern::create( + { + PlanNode::Kind::kGetVertices, + PlanNode::Kind::kGetEdges, + }, + { + Pattern::create(PlanNode::Kind::kArgument), + }), }), }), }); @@ -56,18 +64,13 @@ StatusOr PushLimitDownFulltextIndexScanRule2::transfor OptContext *octx, const MatchedResult &matched) const { auto limitGroupNode = matched.result().node; const auto limit = static_cast(limitGroupNode->node()); - auto newLimit = static_cast(limit->clone()); - newLimit->setOutputVar(limit->outputVar()); - auto newLimitGroupNode = OptGroupNode::create(octx, newLimit, limitGroupNode->group()); auto joinGroupNode = matched.result({0, 0}).node; auto join = static_cast(joinGroupNode->node()); auto newJoin = static_cast(join->clone()); - auto newJoinGroup = OptGroup::create(octx); - auto newJoinGroupNode = newJoinGroup->makeGroupNode(newJoin); + auto newJoinGroupNode = OptGroupNode::create(octx, newJoin, limitGroupNode->group()); - newLimitGroupNode->dependsOn(newJoinGroup); - newLimit->setInputVar(newJoin->outputVar()); + newJoin->setOutputVar(limit->outputVar()); auto ftGroupNode = matched.result({0, 0, 0}).node; const auto ft = static_cast(ftGroupNode->node()); @@ -83,16 +86,25 @@ StatusOr PushLimitDownFulltextIndexScanRule2::transfor newFtGroupNode->dependsOn(dep); } - auto exploreGroupNode = matched.result({0, 0, 1}).node; + auto projGroupNode = matched.result({0, 0, 1}).node; + auto proj = static_cast(projGroupNode->node()); + auto newProj = static_cast(proj->clone()); + auto newProjGroup = OptGroup::create(octx); + auto newProjGroupNode = newProjGroup->makeGroupNode(newProj); + + newJoinGroupNode->dependsOn(newProjGroup); + newJoin->setRightVar(newProj->outputVar()); + + auto exploreGroupNode = matched.result({0, 0, 1, 0}).node; auto explore = static_cast(exploreGroupNode->node()); auto newExplore = static_cast(explore->clone()); auto newExploreGroup = OptGroup::create(octx); auto newExploreGroupNode = newExploreGroup->makeGroupNode(newExplore); - newJoinGroupNode->dependsOn(newExploreGroup); - newJoin->setRightVar(newExplore->outputVar()); + newProjGroupNode->dependsOn(newExploreGroup); + newProj->setInputVar(newExplore->outputVar()); - auto argGroupNode = matched.result({0, 0, 1, 0}).node; + auto argGroupNode = matched.result({0, 0, 1, 0, 0}).node; auto arg = static_cast(argGroupNode->node()); auto newArg = static_cast(arg->clone()); auto newArgGroup = OptGroup::create(octx); @@ -106,7 +118,7 @@ StatusOr PushLimitDownFulltextIndexScanRule2::transfor TransformResult result; result.eraseAll = true; - result.newGroupNodes.emplace_back(newLimitGroupNode); + result.newGroupNodes.emplace_back(newJoinGroupNode); return result; } diff --git a/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.h b/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.h index 30bb300ad02..3820e2aba33 100644 --- a/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.h +++ b/src/graph/optimizer/rule/PushLimitDownFulltextIndexScanRule2.h @@ -22,17 +22,18 @@ namespace opt { // // Limit (count=3, offset=1) // `- HashInnerJoin -// |- GetVertices/GetEdges -// | `- Argument +// |- Project +// | `- GetVertices/GetEdges +// | `- Argument // `- FulltextIndexScan // // After: // -// Limit (count=3, offset=1) -// `- HashInnerJoin -// |- GetVertices/GetEdges -// | `- Argument -// `- FulltextIndexScan (limit=4, offset=1) +// HashInnerJoin +// |- Project +// | `- GetVertices/GetEdges +// | `- Argument +// `-FulltextIndexScan (limit=4, offset=1) // class PushLimitDownFulltextIndexScanRule2 final : public OptRule { diff --git a/tests/tck/features/fulltext_index/FulltextIndexScan.feature b/tests/tck/features/fulltext_index/FulltextIndexScan.feature index a29349b8cb3..d92361c5a01 100644 --- a/tests/tck/features/fulltext_index/FulltextIndexScan.feature +++ b/tests/tck/features/fulltext_index/FulltextIndexScan.feature @@ -23,7 +23,7 @@ Feature: FulltextIndexTest When executing query: """ CREATE FULLTEXT TAG INDEX nebula_index_tag2_prop1 on tag2(prop1); - CREATE FULLTEXT TAG INDEX nebula_index_tag2_prop2 on tag2(prop2); + CREATE FULLTEXT TAG INDEX nebula_index_tag2_props on tag2(prop1, prop2); CREATE FULLTEXT EDGE INDEX nebula_index_edge2_prop1 on edge2(prop1); """ Then the execution should be successful @@ -53,7 +53,7 @@ Feature: FulltextIndexTest """ Then the execution should be successful And wait 10 seconds - When executing query: + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -65,7 +65,13 @@ Feature: FulltextIndexTest Then the result should be, in any order: | id | prop1 | prop2 | | "1" | "abc" | "nebula graph" | - When executing query: + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 5 | Project | 14 | | | + | 14 | GetVertices | 15 | | | + | 15 | FulltextIndexScan | 0 | | | + | 0 | Start | | | | + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -78,7 +84,14 @@ Feature: FulltextIndexTest Then the result should be, in any order: | id | prop1 | prop2 | | "1" | "abc" | "nebula graph" | - When executing query: + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 10 | Project | 11 | | | + | 11 | Limit | 13 | | {"count": 3} | + | 13 | GetVertices | 14 | | {"limit": 3} | + | 14 | FulltextIndexScan | 0 | | {"limit": 3} | + | 0 | Start | | | | + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -90,7 +103,13 @@ Feature: FulltextIndexTest """ Then the result should be, in any order: | id | prop1 | prop2 | - When executing query: + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 10 | Project | 15 | | | + | 15 | GetVertices | 16 | | {"limit":4} | + | 16 | FulltextIndexScan | 0 | | {"offset":1, "limit":4} | + | 0 | Start | | | | + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -103,7 +122,16 @@ Feature: FulltextIndexTest Then the result should be, in any order: | id | prop1 | prop2 | sc | | "1" | "abc" | "nebula graph" | 1.7917595 | - When executing query: + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 6 | Project | 5 | | | + | 5 | HashInnerJoin | 1,4 | | | + | 1 | FulltextIndexScan | 0 | | | + | 0 | Start | | | | + | 4 | Project | 3 | | | + | 3 | GetVertices | 2 | | | + | 2 | Argument | | | | + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -117,7 +145,16 @@ Feature: FulltextIndexTest Then the result should be, in any order: | id | prop1 | prop2 | sc | | "1" | "abc" | "nebula graph" | 1.7917595 | - When executing query: + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 9 | Project | 10 | | | + | 10 | HashInnerJoin | 11,12 | | | + | 11 | FulltextIndexScan | 0 | | {"limit":3} | + | 0 | Start | | | | + | 12 | Project | 13 | | | + | 13 | GetVertices | 14 | | | + | 14 | Argument | | | | + When profiling query: """ LOOKUP ON tag2 WHERE ES_QUERY(nebula_index_tag2_prop1, "abc") @@ -130,10 +167,19 @@ Feature: FulltextIndexTest """ Then the result should be, in any order: | id | prop1 | prop2 | sc | + And the execution plan should be: + | id | name | dependencies | profiling data | operator info | + | 9 | Project | 10 | | | + | 10 | HashInnerJoin | 11,12 | | | + | 11 | FulltextIndexScan | 0 | | {"offset":1,"limit":4} | + | 0 | Start | | | | + | 12 | Project | 13 | | | + | 13 | GetVertices | 14 | | | + | 14 | Argument | | | | When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1, @@ -152,7 +198,7 @@ Feature: FulltextIndexTest When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1, @@ -167,7 +213,7 @@ Feature: FulltextIndexTest When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1, @@ -182,7 +228,7 @@ Feature: FulltextIndexTest When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1, @@ -202,7 +248,7 @@ Feature: FulltextIndexTest When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1, @@ -218,7 +264,7 @@ Feature: FulltextIndexTest When executing query: """ LOOKUP ON tag2 - WHERE ES_QUERY(nebula_index_tag2_prop2, "nebula") + WHERE ES_QUERY(nebula_index_tag2_props, "nebula") YIELD id(vertex) AS id, tag2.prop1 AS prop1,