From 7e83d9af9f18508b5010a28e9cc1153072d1df37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:24:33 +0100 Subject: [PATCH] Cherry Pick PRs 831 & 851 (#854) Co-authored-by: Pontus Melke --- .../planning-and-tuning/operators/index.adoc | 97 +++- .../operators/operators-detail.adoc | 524 +++++++++++++++--- 2 files changed, 534 insertions(+), 87 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/operators/index.adoc b/modules/ROOT/pages/planning-and-tuning/operators/index.adoc index 484ad1c63..cf830c219 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/index.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/index.adoc @@ -18,7 +18,7 @@ This table comprises all the execution plan operators ordered lexicographically. * _Eager_ operators xref::planning-and-tuning/execution-plans.adoc#lazy-eager-evaluation[accumulate all their rows] before piping them to the next operator. -[cols="35a,35a,6,10,14", options="header"] +[cols="35a,35a,8,12,18", options="header"] |=== | Name | Description | Leaf? | Updating? | Considerations @@ -49,7 +49,14 @@ Tests for the absence of a pattern predicate. | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[Argument] -| Indicates the variable to be used as an argument to the right-hand side of an `Apply` operator. +| Indicates the variable to be used as an argument to the right-hand side of an xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. +| label:yes[] +| +| + +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument-tracker[ArgumentTracker] +| Used to ensure row-by-row semantics. +Restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] to not batch operations in larger chunks. | label:yes[] | | @@ -64,7 +71,7 @@ Tests for the absence of a pattern predicate. | Ensures that no relationship property uniqueness constraints are violated. | | -| +| label:new[Introduced in 5.8] | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-asserting-multi-node-index-seek[AssertingMultiNodeIndexSeek] | Used to ensure that no property uniqueness constraints are violated. @@ -120,8 +127,14 @@ Tests for the absence of a pattern predicate. | | +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-by-element-id-seek[DirectedRelationshipByElementIdSeek] +| Reads one or more relationships by element id (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]) from the relationship store and produces the relationship as well as the source and target node of the relationship. +| label:yes[] +| +| + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-by-id-seek[DirectedRelationshipByIdSeek] -| Reads one or more relationships by id from the relationship store. +| Reads one or more relationships by id (specified via the function xref::functions/scalar.adoc#functions-id[Id()]) from the relationship store, and produces the relationship as well as the source and target node of the relationship. | label:yes[] | | @@ -224,7 +237,7 @@ Tests for the absence of a pattern predicate. | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-exhaustive-limit[ExhaustiveLimit] a| -The `ExhaustiveLimit` operator is similar to the `Limit` operator, but always exhausts the input. +The `ExhaustiveLimit` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-limit[`Limit`]operator, but always exhausts the input. Used when combining `LIMIT` and updates. | | @@ -260,7 +273,7 @@ Yields rows from the left-hand operator and discards rows from the right-hand op | Fetches all nodes that have all of the provided labels from the node label index. | label:yes[] | -| +| label:new[Introduced in 5.5] | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-let-anti-semi-apply[LetAntiSemiApply] a| @@ -307,7 +320,7 @@ Tests for the presence of a pattern predicate in queries containing multiple pat | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-locking-merge[LockingMerge] -| Similar to the `Merge` operator but will lock the start and end node when creating a relationship if necessary. +| Similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-merge[`Merge`] operator but will lock the start and end node when creating a relationship if necessary. | | | @@ -324,14 +337,14 @@ Tests for the presence of a pattern predicate in queries containing multiple pat | | -| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-elementid-seek[NodeByElementIdSeek] -| Reads one or more nodes by ID from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-element-id-seek[NodeByElementIdSeek] +| Reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. | label:yes[] | -| +| label:new[Introduced in 5.3] | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-id-seek[NodeByIdSeek] -| Reads one or more nodes by ID from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. +| Reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. | label:yes[] | | @@ -408,6 +421,13 @@ Tests for the presence of a pattern predicate in queries containing multiple pat | | +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-nullify-metadata[NullifyMetadata] +| responsible for cleaning up the state produced by xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-repeat[`Repeat(Trail)`]. +It is only planned directly after `Repeat(Trail)`. +| +| +| label:new[Introduced in 5.9] + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-optional[Optional] | Yields a single row with all columns set to `null` if no data is returned by its source. | @@ -427,15 +447,14 @@ Tests for the presence of a pattern predicate in queries containing multiple pat | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-ordered-aggregation[OrderedAggregation] -a| -Like `EagerAggregation` but relies on the ordering of incoming rows. -Is not eager. +| Similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator but relies on the ordering of incoming rows. +It is not eager. | | | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-ordered-distinct[OrderedDistinct] -| Like `Distinct` but relies on the ordering of incoming rows. +| Similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-distinct[`DISTINCT`] operator but relies on the ordering of incoming rows. | | | @@ -486,7 +505,7 @@ Is not eager. | Solves quantified path patterns. | | -| +| label:new[Introduced in 5.9] | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-remove-labels[RemoveLabels] | Deletes labels from a node. @@ -495,16 +514,14 @@ Is not eager. | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-roll-up-apply[RollUpApply] -a| -Performs a nested loop. +| Performs a nested loop. Executes a pattern expression or pattern comprehension. | | | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-select-or-anti-semi-apply[SelectOrAntiSemiApply] -a| -Performs a nested loop. +| Performs a nested loop. Tests for the absence of a pattern predicate if an expression predicate evaluates to `false`. | | @@ -540,6 +557,12 @@ Tests for the absence of a pattern predicate if an expression predicate evaluate | label:yes[] | +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-set-properties[SetProperties] +| Used when setting multiple properties on a node or relationship. +| +| label:yes[] +| + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-set-relationship-properties-from-map[SetRelationshipPropertiesFromMap] | Sets properties from a map on a relationship. | @@ -600,6 +623,12 @@ Tests for the absence of a pattern predicate if an expression predicate evaluate | | label:eager[] +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-subquery-foreach[SubqueryForeach] +| Works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`]operator but it is only used for executing subqueries. +| +| +| + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-terminate-transactions[TerminateTransactions] | Terminate transactions with the given IDs. | label:yes[] @@ -612,20 +641,32 @@ Tests for the absence of a pattern predicate if an expression predicate evaluate | | label:eager[] +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-transaction-apply[TransactionApply] +| Works like the xref:planning-and-tuning/operators/operators-detail#query-plan-apply[`Apply`] operator but will commit the current transaction after a specified number of rows. +| +| +| + +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-transaction-foreach[TransactionForeach] +| Works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`] operator but will commit the current transaction after a specified number of rows. +| +| +| + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-build[TriadicBuild] -| The `TriadicBuild` operator is used in conjunction with `TriadicFilter` to solve triangular queries. +| Used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-filter[`TriadicFilter`] to solve triangular queries. | | | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-filter[TriadicFilter] -| The `TriadicFilter` operator is used in conjunction with `TriadicBuild` to solve triangular queries. +| Used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-build[`TriadicBuild`] to solve triangular queries. | | | | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-selection[TriadicSelection] -| Solves triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. +| Solves triangular queries, such as the very common 'find my friends-of-friends that are not already my friends'. | | | @@ -636,8 +677,16 @@ Tests for the absence of a pattern predicate if an expression predicate evaluate | | +| xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-by-element-id-seek[UndirectedRelationshipByElementIdSeek] +| Reads one or more relationships by element id (specified via the function xref::functions/scalar.adoc#functions-elementid[ElementId()]) from the relationship store. +As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. +| label:yes[] +| +| + | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-by-id-seek[UndirectedRelationshipByIdSeek] -| Reads one or more relationships by ID from the relationship store. +| Reads one or more relationships by id (specified via the function xref::functions/scalar.adoc#functions-id[Id()]) from the relationship store. +As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. | label:yes[] | | diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index e797a31cf..9c8ad3d0c 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -311,11 +311,54 @@ Total database accesses: 2, total allocated memory: 184 ====== +[[query-plan-directed-relationship-by-element-id-seek]] +== Directed Relationship By Element Id Seek +// DirectedRelationshipByElementIdSeek + +The `DirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]) and produces the relationship as well as the source and target node of the relationship. + + +.DirectedRelationshipByElementIdSeek +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (n1)-[r]->() +WHERE elementId(r) = 0 +RETURN r, n1 +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | r, n1 | 1 | 0 | 0 | 0 | 0/0 | 0.314 | | +| | +----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +DirectedRelationshipByElementIdSeek | 1 | (n1)-[r]->(anon_0) WHERE elementId(r) = $autoint_0 | 1 | 0 | 0 | 248 | 0/0 | 2.337 | In Pipeline 0 | ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ + +Total database accesses: 0, total allocated memory: 312 +---- + +====== + [[query-plan-directed-relationship-by-id-seek]] == Directed Relationship By Id Seek // DirectedRelationshipByIdSeek -The `DirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store, and produces both the relationship and the nodes on either side. +The `DirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store, and produces the relationship as well as the source and target node of the relationship. .DirectedRelationshipByIdSeek @@ -326,7 +369,7 @@ The `DirectedRelationshipByIdSeek` operator reads one or more relationships by i ---- PROFILE MATCH (n1)-[r]->() -WHERE elementId(r) = 0 +WHERE id(r) = 0 RETURN r, n1 ---- @@ -341,31 +384,28 @@ Runtime version {neo4j-version-minor} Batch size 128 -+-------------------------------+----+---------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------------+----+---------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | r, n1 | 1 | 0 | 0 | | | | | -| | +----+---------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | elementId(r) = $autoint_0 | 1 | 0 | 0 | | | | | -| | +----+---------------------------+----------------+------+---------+----------------+ | | | -| +DirectedAllRelationshipsScan | 2 | (n1)-[r]->(anon_0) | 3 | 0 | 0 | 248 | 1/0 | 0.134 | Fused in Pipeline 0 | -+-------------------------------+----+---------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | r, n1 | 1 | 1 | 7 | 0 | | | | +| | +----+---------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipByIdSeek | 1 | (n1)-[r]->(anon_0) WHERE id(r) = $autoint_0 | 1 | 1 | 1 | 248 | 3/0 | 0.483 | Fused in Pipeline 0 | ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 8, total allocated memory: 312 ---- ====== +[[query-plan-undirected-relationship-by-element-id-seek]] +== Undirected Relationship By Element Id Seek +// UndirectedRelationshipByElementIdSeek -[[query-plan-undirected-relationship-by-id-seek]] -== Undirected Relationship By Id Seek -// UndirectedRelationshipByIdSeek - -The `UndirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store. +The `UndirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]). As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. -.UndirectedRelationshipByIdSeek +.UndirectedRelationshipByElementIdSeek ====== .Query @@ -401,6 +441,50 @@ Total database accesses: 1, total allocated memory: 184 ====== +[[query-plan-undirected-relationship-by-id-seek]] +== Undirected Relationship By Id Seek +// UndirectedRelationshipByIdSeek + +The `UndirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-id[Id()]). +As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. + + +.UndirectedRelationshipByIdSeek +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (n1)-[r]-() +WHERE id(r) = 1 +RETURN r, n1 +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | r, n1 | 2 | 2 | 14 | 0 | | | | +| | +----+--------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipByIdSeek | 1 | (n1)-[r]-(anon_0) WHERE id(r) = $autoint_0 | 2 | 2 | 1 | 248 | 3/0 | 1.005 | Fused in Pipeline 0 | ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 15, total allocated memory: 312 +---- + +====== + [[query-plan-directed-relationship-index-contains-scan]] == Directed Relationship Index Contains Scan @@ -734,7 +818,6 @@ Total database accesses: 13, total allocated memory: 184 [[query-plan-intersection-node-by-labels-scan]] == Intersection Node By Labels Scan // IntersectionNodeByLabelsScan -// New in 5.4 _This feature was introduced in Neo4j 5.5._ @@ -776,8 +859,11 @@ Total database accesses: 13, total allocated memory: 184 [[query-plan-directed-all-relationships-scan]] -== Directed All Relationships Scan == +== Directed All Relationships Scan +//DirectedAllRelationshipsScan + The `DirectedAllRelationshipsScan` operator fetches all relationships and their start and end nodes in the database. + ====== .Query @@ -812,7 +898,8 @@ Total database accesses: 28, total allocated memory: 184 ====== [[query-plan-undirected-all-relationships-scan]] -== Undirected All Relationships Scan == +== Undirected All Relationships Scan +//UndirectedAllRelationshipsScan The `UndirectedAllRelationshipsScan` operator fetches all relationships and their start and end nodes in the database. ====== @@ -933,7 +1020,7 @@ Total database accesses: 13, total allocated memory: 184 [[query-plan-directed-union-relationship-types-scan]] == Directed Union Relationship Types Scan -// DirectedUnionRelationshipTypeScan +// DirectedUnionRelationshipTypesScan The `DirectedUnionRelationshipTypeScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. @@ -976,7 +1063,7 @@ Total database accesses: 14, total allocated memory: 184 [[query-plan-undirected-union-relationship-types-scan]] == Undirected Union Relationship Types Scan -// UndirectedUnionRelationshipTypeScan +// UndirectedUnionRelationshipTypesScan The `UndirectedUnionRelationshipTypeScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. @@ -1064,7 +1151,7 @@ Total database accesses: 1, total allocated memory: 184 == Node By Id Seek // NodeByIdSeek -The `NodeByIdSeek` operator reads one or more nodes by ID from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. +The `NodeByIdSeek` operator reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. .NodeByIdSeek @@ -1075,7 +1162,7 @@ The `NodeByIdSeek` operator reads one or more nodes by ID from the node store, s ---- PROFILE MATCH (n) -WHERE elementId(n) = 0 +WHERE id(n) = 0 RETURN n ---- @@ -1090,17 +1177,17 @@ Runtime version {neo4j-version-minor} Batch size 128 -+----------------------+----+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------+----+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | n | 1 | 0 | 0 | | 0/0 | 0.042 | | -| | +----+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +NodeByElementIdSeek | 1 | n WHERE elementId(n) = $autoint_0 | 1 | 0 | 1 | 248 | 0/0 | 0.107 | In Pipeline 0 | -+----------------------+----+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | n | 1 | 1 | 2 | 0 | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +NodeByIdSeek | 1 | n WHERE id(n) = $autoint_0 | 1 | 1 | 1 | 248 | 2/0 | 1.109 | Fused in Pipeline 0 | ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +Total database accesses: 3, total allocated memory: 312 - -Total database accesses: 1, total allocated memory: 184 +1 row ---- ====== @@ -1610,7 +1697,7 @@ Total database accesses: 11, total allocated memory: 184 == Apply // Apply -All the different `Apply` operators (listed below) share the same basic functionality: they perform a nested loop by taking a single row from the left-hand side, and using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[Argument] operator on the right-hand side, execute the operator tree on the right-hand side. +All the different `Apply` operators (listed below) share the same basic functionality: they perform a nested loop by taking a single row from the left-hand side, and using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[`Argument`] operator on the right-hand side, execute the operator tree on the right-hand side. The versions of the `Apply` operators differ in how the results are managed. The `Apply` operator (i.e. the standard version) takes the row produced by the right-hand side -- which at this point contains data from both the left-hand and right-hand sides -- and yields it. @@ -1660,7 +1747,7 @@ Total database accesses: 2, total allocated memory: 2216 == Semi Apply // SemiApply -The `SemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `SemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. If the right-hand side operator yields at least one row, the row from the left-hand side operator is yielded by the `SemiApply` operator. This makes `SemiApply` a filtering operator, used mostly for pattern predicates in queries. @@ -1715,7 +1802,7 @@ Total database accesses: 142, total allocated memory: 64 == Anti Semi Apply // AntiSemiApply -The `AntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `AntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. If the right-hand side operator yields no rows, the row from the left-hand side operator is yielded by the `AntiSemiApply` operator. This makes `AntiSemiApply` a filtering operator, used for pattern predicates in queries. @@ -1768,6 +1855,58 @@ Total database accesses: 166, total allocated memory: 976 ====== +[[query-plan-transaction-apply]] +== TransactionApply +// TransactionApply + +`TransactionApply` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator but will commit the current transaction after a specified number of rows. + +.TransactionApply +====== + +.Query +[source, cypher] +---- +PROFILE +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL { + WITH line + CREATE (a: Artist {name: line[0]}) + RETURN a +} IN TRANSACTIONS OF 100 ROWS +RETURN a; +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | a | 10 | 4 | 8 | 0 | | | | +| | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | +| +TransactionApply | 1 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 2152 | 0/0 | 2.036 | Fused in Pipeline 3 | +| |\ +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Create | 2 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 16 | | | | | +| | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 3 | line | 10 | 4 | 0 | 3472 | 0/0 | 32.746 | Fused in Pipeline 2 | +| | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +LoadCSV | 4 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 24, total allocated memory: 5472 +---- + +====== + [[query-plan-anti]] == Anti @@ -1838,7 +1977,7 @@ Total database accesses: 178, total allocated memory: 6744 == Let Semi Apply // LetSemiApply -The `LetSemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `LetSemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. When a query contains multiple pattern predicates separated with `OR`, `LetSemiApply` will be used to evaluate the first of these. It will record the result of evaluating the predicate but will leave any filtering to another operator. In the example, `LetSemiApply` will be used to check for the presence of the `FRIENDS_WITH` relationship from each person. @@ -1902,7 +2041,7 @@ Total database accesses: 165, total allocated memory: 64 == Let Anti Semi Apply // LetAntiSemiApply -The `LetAntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `LetAntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. When a query contains multiple negated pattern predicates -- i.e. predicates separated with `OR`, where at least one predicate contains `NOT` -- `LetAntiSemiApply` will be used to evaluate the first of these. It will record the result of evaluating the predicate but will leave any filtering to another operator. In the example, `LetAntiSemiApply` will be used to check for the absence of the `FRIENDS_WITH` relationship from each person. @@ -1966,7 +2105,7 @@ Total database accesses: 142, total allocated memory: 64 // SelectOrSemiApply The `SelectOrSemiApply` operator tests for the presence of a pattern predicate and evaluates a predicate, -and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. This operator allows for the mixing of normal predicates and pattern predicates that check for the presence of a pattern. First, the normal expression predicate is evaluated, and, only if it returns `false`, is the costly pattern predicate evaluated. @@ -2024,7 +2163,7 @@ Total database accesses: 148, total allocated memory: 2952 == Select Or Anti Semi Apply // SelectOrAntiSemiApply -The `SelectOrAntiSemiApply` operator is used to evaluate `OR` between a predicate and a negative pattern predicate (i.e. a pattern predicate preceded with `NOT`), and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `SelectOrAntiSemiApply` operator is used to evaluate `OR` between a predicate and a negative pattern predicate (i.e. a pattern predicate preceded with `NOT`), and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. If the predicate returns `true`, the pattern predicate is not tested. If the predicate returns `false` or `null`, `SelectOrAntiSemiApply` will instead test the pattern predicate. @@ -2085,7 +2224,7 @@ Total database accesses: 136, total allocated memory: 4208 // LetSelectOrSemiApply The `LetSelectOrSemiApply` operator is planned for pattern predicates that are combined with other predicates using `OR`. -This is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +This is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. .LetSelectOrSemiApply @@ -2147,7 +2286,7 @@ Total database accesses: 179, total allocated memory: 64 // LetSelectOrAntiSemiApply The `LetSelectOrAntiSemiApply` operator is planned for negated pattern predicates -- i.e. pattern predicates preceded with `NOT` -- that are combined with other predicates using `OR`. -This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. .LetSelectOrAntiSemiApply @@ -2262,7 +2401,7 @@ Total database accesses: 4, total allocated memory: 184 == Locking Merge // LockingMerge -The `LockingMerge` operator is just like a normal `Merge` but will lock the start and end node when creating a relationship if necessary. +The `LockingMerge` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-merge[`Merge`] operator but will lock the start and end node when creating a relationship if necessary. .LockingMerge @@ -2316,7 +2455,7 @@ Total database accesses: 15, total allocated memory: 2232 // RollUpApply The `RollUpApply` operator is used to execute an expression which takes as input a pattern, and returns a list with content from the matched pattern; for example, when using a pattern expression or pattern comprehension in a query. -This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. .RollUpApply @@ -2368,7 +2507,7 @@ Total database accesses: 153, total allocated memory: 64 == Argument // Argument -The `Argument` operator indicates the variable to be used as an argument to the right-hand side of an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator. +The `Argument` operator indicates the variable to be used as an argument to the right-hand side of an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. .Argument @@ -2416,6 +2555,63 @@ Total database accesses: 15, total allocated memory: 2232 ====== +[[query-plan-argument-tracker]] +== Argument Tracker +// ArgumentTracker + +The `ArgumentTracker` operator is used to ensure row-by-row semantics. +This restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] to not batch operations in larger chunks. + +.ArgumentTracker +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (s:Person {name: 'me'}) +CALL { + WITH s + SET s.seen = coalesce(s.seen + 1,1) + RETURN s.seen AS result +} +RETURN result; +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + ++--------------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | result | 0 | 0 | 0 | | | | | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Projection | 1 | s.seen AS result | 0 | 0 | 0 | | | | | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | 2 | | 0 | 0 | 0 | | | | | +| |\ +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +ArgumentTracker | 7 | | 0 | 0 | 0 | 696 | | | | +| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Eager | 3 | | 0 | 0 | 0 | 696 | 0/0 | 0.000 | Fused in Pipeline 2 | +| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +SetProperty | 4 | s.seen = coalesce(s.seen + $autoint_1, $autoint_2) | 0 | 0 | 0 | | | | | +| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | s | 0 | 0 | 0 | 256 | 0/0 | 0.000 | Fused in Pipeline 1 | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeIndexSeek | 6 | RANGE INDEX s:Person(name) WHERE name = $autostring_0 | 0 | 0 | 1 | 376 | 1/0 | 0.286 | In Pipeline 0 | ++--------------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + + +Total database accesses: 47, total allocated memory: 4144 +---- + +====== // --- expand operators --- @@ -2873,6 +3069,61 @@ Total database accesses: 318, total allocated memory: 208 ====== +[[query-plan-nullify-metadata]] +== Nullify Metadata +// NullifyMetadata +_This feature was introduced in Neo4j 5.9._ + +`NullifyMetadata` is responsible for cleaning up the state produced by xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-repeat[`Repeat(Trail)`]. +It is only planned directly after `Repeat(Trail)`. + +.NullifyMetadata +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (me:Person) ((a)-[:FRIENDS_WITH]-(b) WHERE a.name <> b.name){1,2} (friend:Person) +RETURN me, friend +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++------------------+----+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 15 | 48 | 0 | | | | | +| | +----+-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 15 | 48 | 96 | | | | | +| | +----+-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 7 | | 15 | 48 | 0 | | | | | +| | +----+-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 15 | 48 | 0 | 16784 | 0/0 | 1.146 | Fused in Pipeline 2 | +| |\ +----+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | not a.name = b.name AND isRepeatTrailUnique(anon_2) | 5 | 48 | 216 | | | | | +| | | +----+-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (a)-[anon_2:FRIENDS_WITH]-(b) | 10 | 72 | 151 | | | | | +| | | +----+-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | a | 14 | 38 | 0 | 3112 | 3/0 | 6.279 | Fused in Pipeline 1 | +| | +----+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 6 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 3.970 | In Pipeline 0 | ++------------------+----+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 318, total allocated memory: 208 +---- + +====== + [[query-plan-assert-same-node]] == Assert Same Node // AssertSameNode @@ -2933,7 +3184,7 @@ _This feature was introduced in Neo4j 5.8._ The `AssertSameRelationship` operator is used to ensure that no relationship property uniqueness constraints are violated in the slotted and interpreted runtime. The example looks for the presence of a `WORKS_IN` relationship with the supplied `id` and `badgeNumber`. If it can't be found, then it will be created. -Owing to the existence of two property uniqueness constraints on `:WORKS_IN(id)` and `:WORKS_IN(badgeNumber)`, any relationship that would be found by the `DirectedRelationshipUniqueIndexSeek` operator must be the very same relationship or the constraints would be violated. +Owing to the existence of two property uniqueness constraints on `:WORKS_IN(id)` and `:WORKS_IN(badgeNumber)`, any relationship that would be found by the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-unique-index-seek[`DirectedRelationshipUniqueIndexSeek`] operator must be the very same relationship or the constraints would be violated. .AssertSameRelationship @@ -3304,8 +3555,8 @@ Total database accesses: 211, total allocated memory: 4312 == Triadic Selection // TriadicSelection -The `TriadicSelection` operator is used to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. -It does so by putting all the friends into a set, and uses the set to check if the friend-of-friends are already connected to me. +The `TriadicSelection` operator is used to solve triangular queries, such as the very common 'find my friends-of-friends that are not already my friend'. +It does so by putting all the friends into a set, and uses the set to check if the friends-of-friends are already connected to me. The example finds the names of all friends of my friends that are not already my friends. @@ -3362,8 +3613,8 @@ Total database accesses: 246, total allocated memory: 64 == Triadic Build // TriadicBuild -The `TriadicBuild` operator is used in conjunction with `TriadicFilter` to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. -These two operators are specific to Pipelined runtime and together perform the same logic as `TriadicSelection` does for other runtimes. +The `TriadicBuild` operator is used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-filter[`TriadicFilter`] to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. +These two operators are specific to Pipelined runtime and together perform the same logic as xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-selection[`TriadicSelection`] does for other runtimes. `TriadicBuild` builds a set of all friends, which is later used by `TriadicFilter`. The example finds the names of all friends of my friends that are not already my friends. @@ -3427,8 +3678,8 @@ Total database accesses: 256, total allocated memory: 7376 == Triadic Filter // TriadicFilter -The `TriadicFilter` operator is used in conjunction with `TriadicBuild` to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. -These two operators are specific to Pipelined runtime and together perform the same logic as `TriadicSelection` does for other runtimes. +The `TriadicFilter` operator is used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-build[`TriadicBuild`] to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. +These two operators are specific to Pipelined runtime and together perform the same logic as xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-selection[`TriadicSelection`] does for other runtimes. `TriadicFilter` uses a set of friends previously built by `TriadicBuild` to check if the friend-of-friends are already connected to me. The example finds the names of all friends of my friends that are not already my friends. @@ -3554,7 +3805,6 @@ In an analogous manner to the xref::planning-and-tuning/operators/operators-deta [source, cypher] ---- PROFILE -CYPHER runtime=slotted FOREACH (value IN [1,2,3] | CREATE (:Person {age: value})) ---- @@ -3582,6 +3832,110 @@ Total database accesses: 9, total allocated memory: 64 ====== +[[query-plan-transaction-foreach]] +== TransactionForeach +// TransactionForeach + +`TransactionForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`] operator but will commit the current transaction after a specified number of rows. + +.TransactionForeach +====== + +.Query +[source, cypher] +---- +PROFILE +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL { + WITH line + CREATE (a: Artist {name: line[0]}) +} IN TRANSACTIONS OF 100 ROWS +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + +++---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | + +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +TransactionForeach | 2 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 4856 | | | | + | |\ +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | + | | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.712 | Fused in Pipeline 2 | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | + +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + + Total database accesses: 12, total allocated memory: 5704 +---- + +====== + +[[query-plan-subquery-foreach]] +== SubqueryForeach +// SubqueryForeach + +`SubqueryForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`]operator but it is only used for executing subqueries. + +.SubqueryForeach +====== + +.Query +[source, cypher] +---- +PROFILE +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL { + WITH line + CREATE (a: Artist {name: line[0]}) +} +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | +| | +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | +| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +SubqueryForeach | 2 | | 10 | 4 | 0 | 4080 | | | | +| |\ +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | +| | | +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.852 | Fused in Pipeline 2 | +| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 12, total allocated memory: 4928 +---- + +====== + [[query-plan-eager]] == Eager @@ -3712,7 +4066,7 @@ Total database accesses: 117, total allocated memory: 2664 == Ordered Aggregation // OrderedAggregation -The `OrderedAggregation` operator is an optimization of the `EagerAggregation` operator that takes advantage of the ordering of the incoming rows. +The `OrderedAggregation` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator that takes advantage of the ordering of the incoming rows. This operator uses lazy evaluation and has a lower memory pressure in the system than the `EagerAggregation` operator. @@ -3760,7 +4114,7 @@ Total database accesses: 3, total allocated memory: 352 // NodeCountFromCountStore The `NodeCountFromCountStore` operator uses the count store to answer questions about node counts. -This is much faster than the `EagerAggregation` operator which achieves the same result by actually counting. +This is much faster than the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator which achieves the same result by actually counting. However, as the count store only stores a limited range of combinations, `EagerAggregation` will still be used for more complex queries. For example, we can get counts for all nodes, and nodes with a label, but not nodes with more than one label. @@ -3802,11 +4156,11 @@ Total database accesses: 1, total allocated memory: 184 [[query-plan-relationship-count-from-count-store]] -== Relationship Count From Count Store == +== Relationship Count From Count Store // RelationshipCountFromCountStore The `RelationshipCountFromCountStore` operator uses the count store to answer questions about relationship counts. -This is much faster than the `EagerAggregation` operator which achieves the same result by actually counting. +This is much faster than the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator which achieves the same result by actually counting. However, as the count store only stores a limited range of combinations, `EagerAggregation` will still be used for more complex queries. For example, we can get counts for all relationships, relationships with a type, relationships with a label on one end, but not relationships with labels on both end nodes. @@ -3900,7 +4254,7 @@ Total database accesses: 95, total allocated memory: 432 == Ordered Distinct // OrderedDistinct -The `OrderedDistinct` operator is an optimization of the `Distinct` operator that takes advantage of the ordering of the incoming rows. +The `OrderedDistinct` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-distinct[`Distinct`] operator that takes advantage of the ordering of the incoming rows. This operator has a lower memory pressure in the system than the `Distinct` operator. @@ -4139,7 +4493,7 @@ Total database accesses: 85, total allocated memory: 1272 == Partial Sort // PartialSort -The `PartialSort` operator is an optimization of the `Sort` operator that takes advantage of the ordering of the incoming rows. +The `PartialSort` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-sort[`Sort`] operator that takes advantage of the ordering of the incoming rows. This operator uses lazy evaluation and has a lower memory pressure in the system than the `Sort` operator. Partial sort is only applicable when sorting on multiple columns. @@ -4240,7 +4594,7 @@ Total database accesses: 85, total allocated memory: 1264 == Partial Top // PartialTop -The `PartialTop` operator is an optimization of the `Top` operator that takes advantage of the ordering of the incoming rows. +The `PartialTop` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-top[`Top`] operator that takes advantage of the ordering of the incoming rows. This operator uses lazy evaluation and has a lower memory pressure in the system than the `Top` operator. Partial top is only applicable when sorting on multiple columns. @@ -4393,7 +4747,7 @@ Total database accesses: 0, total allocated memory: 184 // LockNodes - changed in 4.3 // ExhaustiveLimit -The `ExhaustiveLimit` operator is just like a normal `Limit` but will always exhaust the input. +The `ExhaustiveLimit` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-limit[`Limit`] operator but will always exhaust the input. Used when combining `LIMIT` and updates @@ -5170,6 +5524,51 @@ Total database accesses: 106, total allocated memory: 184 ====== +[[query-plan-set-properties]] +== Set Properties +// SetProperties + +The `SetProperties` operator is used when setting multiple properties on a node or relationship. + + +.SetProperties +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (n) +SET n.weekDay = 'Monday', n.meal = 'Lunch' +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++-----------------+----+---------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----+---------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 35 | 0 | 0 | 0 | | | | +| | +----+---------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 35 | 0 | 0 | | | | | +| | +----+---------------------------------------------------+----------------+------+---------+----------------+ | | | +| +SetProperties | 2 | n.weekDay = $autostring_0, n.meal = $autostring_1 | 35 | 35 | 105 | | | | | +| | +----+---------------------------------------------------+----------------+------+---------+----------------+ | | | +| +AllNodesScan | 3 | n | 35 | 35 | 36 | 248 | 3/0 | 152.289 | Fused in Pipeline 0 | ++-----------------+----+---------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 141, total allocated memory: 312 +---- + +====== [[query-plan-create-constraint]] == Create Constraint @@ -5711,4 +6110,3 @@ Total database accesses: 0, total allocated memory: 64 ---- ====== -