Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc082e80

Browse files
committed
Temporarily disable intersection scans
1 parentcc49046 commitc082e80

File tree

11 files changed

+87
-49
lines changed

11 files changed

+87
-49
lines changed

‎community/configuration/src/main/java/org/neo4j/configuration/GraphDatabaseInternalSettings.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,12 @@ public enum EagerAnalysisImplementation {
920920
"internal.cypher.planning_point_indexes_enabled",BOOL,true)
921921
.build();
922922

923+
@Internal
924+
@Description("Feature flag to enable/disable planning use of intersection scans.")
925+
publicstaticfinalSetting<Boolean>planning_intersection_scans_enabled =newBuilder(
926+
"internal.cypher.planning_intersection_scans_enabled",BOOL,false)
927+
.build();
928+
923929
@Internal
924930
@Description(
925931
"Limits the maximum amount of off-heap memory the consistency checker will allocate. The value is given as a factor between 0.1 .. 1 "

‎community/cypher/cypher-config/src/main/scala/org/neo4j/cypher/internal/config/CypherConfiguration.scala‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ class CypherConfiguration private (val config: Config) {
103103
config.get(GraphDatabaseInternalSettings.cypher_enable_extra_semantic_features).asScala.toSet
104104
valplanningTextIndexesEnabled:Boolean= config.get(GraphDatabaseInternalSettings.planning_text_indexes_enabled)
105105

106+
valplanningIntersectionScansEnabled:Boolean=
107+
config.get(GraphDatabaseInternalSettings.planning_intersection_scans_enabled)
108+
106109
valuseLPEagerAnalyzer:Boolean= config.get(
107110
GraphDatabaseInternalSettings.cypher_eager_analysis_implementation
108111
)==GraphDatabaseInternalSettings.EagerAnalysisImplementation.LP

‎community/cypher/cypher-planner/src/main/scala/org/neo4j/cypher/internal/compiler/CypherPlanner.scala‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ class CypherPlannerConfiguration(config: CypherConfiguration, cfg: Config, val p
240240
()=> config.planningPointIndexesEnabled
241241
}
242242

243+
valplanningIntersectionScansEnabled: ()=>Boolean= {
244+
AssertMacros.checkOnlyWhenAssertionsAreEnabled(
245+
!GraphDatabaseInternalSettings.planning_intersection_scans_enabled.dynamic()
246+
)
247+
()=> config.planningIntersectionScansEnabled
248+
}
249+
243250
valpredicatesAsUnionMaxSize: ()=>Int= {
244251
AssertMacros.checkOnlyWhenAssertionsAreEnabled(
245252
!GraphDatabaseInternalSettings.predicates_as_union_max_size.dynamic()

‎community/cypher/cypher-planner/src/main/scala/org/neo4j/cypher/internal/compiler/planner/logical/LogicalPlanningContext.scala‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ object LogicalPlanningContext {
134134
planningTextIndexesEnabled:Boolean=GraphDatabaseInternalSettings.planning_text_indexes_enabled.defaultValue(),
135135
planningRangeIndexesEnabled:Boolean=GraphDatabaseInternalSettings.planning_range_indexes_enabled.defaultValue(),
136136
planningPointIndexesEnabled:Boolean=GraphDatabaseInternalSettings.planning_point_indexes_enabled.defaultValue(),
137+
planningIntersectionScansEnabled:Boolean=
138+
GraphDatabaseInternalSettings.planning_intersection_scans_enabled.defaultValue(),
137139
useLegacyShortestPath:Boolean=GraphDatabaseInternalSettings.use_legacy_shortest_path.defaultValue()
138140
) {
139141

@@ -159,6 +161,7 @@ object LogicalPlanningContext {
159161
planningTextIndexesEnabled:Boolean,
160162
planningRangeIndexesEnabled:Boolean,
161163
planningPointIndexesEnabled:Boolean,
164+
planningIntersectionScansEnabled:Boolean,
162165
useLegacyShortestPath:Boolean
163166
)=>
164167
valbuilder=Seq.newBuilder[Any]
@@ -192,6 +195,9 @@ object LogicalPlanningContext {
192195
if (GraphDatabaseInternalSettings.planning_point_indexes_enabled.dynamic())
193196
builder.addOne(planningPointIndexesEnabled)
194197

198+
if (GraphDatabaseInternalSettings.planning_intersection_scans_enabled.dynamic())
199+
builder.addOne(planningIntersectionScansEnabled)
200+
195201
// use_legacy_shortest_path is dynamic, but documented to not affect caching.
196202
// if (GraphDatabaseInternalSettings.use_legacy_shortest_path.dynamic())
197203
// builder.addOne(useLegacyShortestPath)

‎community/cypher/cypher-planner/src/main/scala/org/neo4j/cypher/internal/compiler/planner/logical/QueryPlanner.scala‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ case object QueryPlanner
102102
planningTextIndexesEnabled= context.config.planningTextIndexesEnabled(),
103103
planningRangeIndexesEnabled= context.config.planningRangeIndexesEnabled(),
104104
planningPointIndexesEnabled= context.config.planningPointIndexesEnabled(),
105+
planningIntersectionScansEnabled= context.config.planningIntersectionScansEnabled(),
105106
useLegacyShortestPath= context.config.useLegacyShortestPath()
106107
)
107108

‎community/cypher/cypher-planner/src/main/scala/org/neo4j/cypher/internal/compiler/planner/logical/steps/intersectionLabelScanLeafPlanner.scala‎

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -39,55 +39,59 @@ case class intersectionLabelScanLeafPlanner(skipIDs: Set[String]) extends LeafPl
3939
interestingOrderConfig:InterestingOrderConfig,
4040
context:LogicalPlanningContext
4141
):Set[LogicalPlan]= {
42-
// Combine for example HasLabels(n, Seq(A)), HasLabels(n, Seq(B)) to n -> Set(A, B)
43-
valcombined:Map[Variable,Set[LabelName]]= {
44-
qg.selections.flatPredicatesSet.foldLeft(Map.empty[Variable,Set[LabelName]]) {
45-
case (acc, current)=> currentmatch {
46-
caseHasLabels(variable@Variable(varName), labels)
47-
if!skipIDs.contains(
48-
varName
49-
)&& context.staticComponents.planContext.canLookupNodesByLabel&& (qg.patternNodes(
50-
varName
51-
)&&!qg.argumentIds(varName))=>
52-
valnewValue= acc.get(variable).map(current=> (current++ labels)).getOrElse(labels.toSet)
53-
acc+ (variable-> newValue)
54-
case _=> acc
55-
}
42+
if (!context.settings.planningIntersectionScansEnabled) {
43+
Set.empty
44+
}else {
45+
// Combine for example HasLabels(n, Seq(A)), HasLabels(n, Seq(B)) to n -> Set(A, B)
46+
valcombined:Map[Variable,Set[LabelName]]= {
47+
qg.selections.flatPredicatesSet.foldLeft(Map.empty[Variable,Set[LabelName]]) {
48+
case (acc, current)=> currentmatch {
49+
caseHasLabels(variable@Variable(varName), labels)
50+
if!skipIDs.contains(
51+
varName
52+
)&& context.staticComponents.planContext.canLookupNodesByLabel&& (qg.patternNodes(
53+
varName
54+
)&&!qg.argumentIds(varName))=>
55+
valnewValue= acc.get(variable).map(current=> (current++ labels)).getOrElse(labels.toSet)
56+
acc+ (variable-> newValue)
57+
case _=> acc
58+
}
59+
}
5660
}
57-
}
5861

59-
// We only create one plan with the intersection of all labels, we could change this to generate all combinations, e.g.
60-
// given labels A, B and C
61-
// - (A,B,C)
62-
// - (A,B)
63-
// - (B,C)
64-
// - (A, C)
65-
// and in that way create more flexibility for the planner to plan things like
66-
//
67-
// .nodeHashJoin("x")
68-
// .|.intersectionNodeByLabelsScan("n", Seq("B", "C"))
69-
// .nodeUniqueIndexSeek("n:A(prop = 42)")
70-
//
71-
// Will leave this as a future potential improvement.
72-
combined.collect {
73-
case (variable, labels)if labels.size>1=>
74-
valprovidedOrder=ResultOrdering.providedOrderForLabelScan(
75-
interestingOrderConfig.orderToSolve,
76-
variable,
77-
context.providedOrderFactory
78-
)
79-
valhints= qg.hints.collect {
80-
case hint@UsingScanHint(`variable`,LabelOrRelTypeName(name))if labels.exists(_.name== name)=> hint
81-
}
82-
context.staticComponents.logicalPlanProducer.planIntersectNodeByLabelsScan(
83-
variable,
84-
labels.toSeq,
85-
Seq(HasLabels(variable, labels.toSeq)(InputPosition.NONE)),
86-
hints.toSeq,
87-
qg.argumentIds,
88-
providedOrder,
89-
context
90-
)
91-
}.toSet
62+
// We only create one plan with the intersection of all labels, we could change this to generate all combinations, e.g.
63+
// given labels A, B and C
64+
// - (A,B,C)
65+
// - (A,B)
66+
// - (B,C)
67+
// - (A, C)
68+
// and in that way create more flexibility for the planner to plan things like
69+
//
70+
// .nodeHashJoin("x")
71+
// .|.intersectionNodeByLabelsScan("n", Seq("B", "C"))
72+
// .nodeUniqueIndexSeek("n:A(prop = 42)")
73+
//
74+
// Will leave this as a future potential improvement.
75+
combined.collect {
76+
case (variable, labels)if labels.size>1=>
77+
valprovidedOrder=ResultOrdering.providedOrderForLabelScan(
78+
interestingOrderConfig.orderToSolve,
79+
variable,
80+
context.providedOrderFactory
81+
)
82+
valhints= qg.hints.collect {
83+
case hint@UsingScanHint(`variable`,LabelOrRelTypeName(name))if labels.exists(_.name== name)=> hint
84+
}
85+
context.staticComponents.logicalPlanProducer.planIntersectNodeByLabelsScan(
86+
variable,
87+
labels.toSeq,
88+
Seq(HasLabels(variable, labels.toSeq)(InputPosition.NONE)),
89+
hints.toSeq,
90+
qg.argumentIds,
91+
providedOrder,
92+
context
93+
)
94+
}.toSet
95+
}
9296
}
9397
}

‎community/cypher/cypher-planner/src/test/scala/org/neo4j/cypher/internal/compiler/planner/LogicalPlanningTestSupport2.scala‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ object LogicalPlanningTestSupport2 extends MockitoSugar {
181181
overridedefpostConditions:Set[StepSequencer.Condition]=Set.empty
182182
}
183183

184-
valdefaultCypherCompilerConfig:CypherPlannerConfiguration=CypherPlannerConfiguration.defaults()
184+
valdefaultCypherCompilerConfig:CypherPlannerConfiguration=CypherPlannerConfiguration.withSettings(
185+
Map(GraphDatabaseInternalSettings.planning_intersection_scans_enabled-> java.lang.Boolean.TRUE)
186+
)
185187

186188
defdefaultParsingConfig(cypherCompilerConfig:CypherPlannerConfiguration):ParsingConfig=
187189
ParsingConfig(

‎community/cypher/cypher-planner/src/test/scala/org/neo4j/cypher/internal/compiler/planner/StatisticsBackedLogicalPlanningConfiguration.scala‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,10 @@ case class StatisticsBackedLogicalPlanningConfigurationBuilder private (
600600
withSetting(GraphDatabaseInternalSettings.planning_point_indexes_enabled,Boolean.box(enabled))
601601
}
602602

603+
defenablePlanningIntersectionScans(enabled:Boolean=true):StatisticsBackedLogicalPlanningConfigurationBuilder= {
604+
withSetting(GraphDatabaseInternalSettings.planning_intersection_scans_enabled,Boolean.box(enabled))
605+
}
606+
603607
defbuild():StatisticsBackedLogicalPlanningConfiguration= {
604608
require(cardinalities.allNodes.isDefined,"Please specify allNodesCardinality using `setAllNodesCardinality`.")
605609
cardinalities.allNodes.foreach(anc=>

‎community/cypher/cypher-planner/src/test/scala/org/neo4j/cypher/internal/compiler/planner/logical/IndexWithProvidedOrderPlanningIntegrationTest.scala‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ abstract class IndexWithProvidedOrderPlanningIntegrationTest(queryGraphSolverSet
9292
overridedefplannerBuilder():StatisticsBackedLogicalPlanningConfigurationBuilder=
9393
super.plannerBuilder()
9494
.enableConnectComponentsPlanner(queryGraphSolverSetup.useIdpConnectComponents)
95+
.enablePlanningIntersectionScans()
9596

9697
caseclassTestOrder(
9798
indexOrder:IndexOrder,

‎community/cypher/cypher-planner/src/test/scala/org/neo4j/cypher/internal/compiler/planner/logical/LeafPlanningIntegrationTest.scala‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ class LeafPlanningIntegrationTest extends CypherFunSuite with LogicalPlanningTes
16331633

16341634
test("should work with label scans of label conjunctions only") {
16351635
valcfg= plannerBuilder()
1636+
.enablePlanningIntersectionScans()
16361637
.setAllNodesCardinality(100)
16371638
.setLabelCardinality("L",50)
16381639
.setLabelCardinality("P",50)
@@ -1659,6 +1660,7 @@ class LeafPlanningIntegrationTest extends CypherFunSuite with LogicalPlanningTes
16591660

16601661
test("should work with label scans of label conjunctions only and solve single scan hint") {
16611662
valcfg= plannerBuilder()
1663+
.enablePlanningIntersectionScans()
16621664
.setAllNodesCardinality(100)
16631665
.setLabelCardinality("L",50)
16641666
.setLabelCardinality("P",50)
@@ -1687,6 +1689,7 @@ class LeafPlanningIntegrationTest extends CypherFunSuite with LogicalPlanningTes
16871689

16881690
test("should work with label scans of label conjunctions only and solve two scan hints") {
16891691
valcfg= plannerBuilder()
1692+
.enablePlanningIntersectionScans()
16901693
.setAllNodesCardinality(100)
16911694
.setLabelCardinality("L",50)
16921695
.setLabelCardinality("P",50)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp