Cypher 计划程序的索引提示

计划程序提示用于在为查询构建执行计划时影响计划程序的决策。计划程序提示使用USING关键字在查询中指定。

强制计划程序行为是一项高级功能,应谨慎使用,仅供经验丰富的开发人员和/或数据库管理员使用,因为它可能会导致查询性能下降。

执行查询时,Neo4j 需要确定在查询图中的哪个位置开始匹配。这是通过查看MATCH子句和WHERE条件并使用这些信息来查找有用的索引或其他起点来完成的。

但是,所选索引并不总是最佳选择。有时多个索引可能是候选索引,并且查询计划程序会从性能的角度选择次优的索引。此外,在某些情况下(尽管很少见),完全不使用索引会更好。

可以通过USING关键字强制 Neo4j 使用特定的起点。这称为给出计划程序提示。

计划程序提示有三种类型

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
RETURN *

上面的查询将在此页面的一些示例中使用。没有任何提示的情况下,将使用一个索引和无连接。

查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+-----------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator        | Details                                                  | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+-----------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults | c, cc, i, p, s, sc                                       |              0 |    0 |       0 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | s.born = $autoint_0 AND s:Scientist                      |              0 |    0 |       0 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (sc)<-[anon_0:RESEARCHED]-(s)                            |              0 |    0 |       0 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | i.year = $autoint_1 AND sc:Science                       |              0 |    0 |       0 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (p)-[i:INVENTED_BY]->(sc)                                |              0 |    0 |       0 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | p.born = $autoint_2 AND p:Pioneer                        |              0 |    0 |       2 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (c)<-[anon_1:LIVES_IN]-(p)                               |              1 |    1 |       3 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | c:City                                                   |              1 |    1 |       2 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (cc)<-[anon_2:PART_OF]-(c)                               |              1 |    1 |       2 |                |                        |           |                     |
| |               +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek  | RANGE INDEX cc:Country(formed) WHERE formed = $autoint_3 |              1 |    1 |       2 |            120 |                    6/1 |     0.506 | Fused in Pipeline 0 |
+-----------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 11, total allocated memory: 208

索引提示

索引提示用于指定计划程序应使用哪个索引作为起点。在查询所使用的特定值的索引统计信息不准确的情况下,这可能是有益的,这会导致计划程序选择非最佳索引。索引提示在适用的MATCH子句之后提供。

可用的索引提示为

提示 计划满足

USING [RANGE | TEXT | POINT] INDEX variable:Label(property)

NodeIndexScanNodeIndexSeek

USING [RANGE | TEXT | POINT] INDEX SEEK variable:Label(property)

NodeIndexSeek

USING [RANGE | TEXT | POINT] INDEX variable:RELATIONSHIP_TYPE(property)

DirectedRelationshipIndexScanUndirectedRelationshipIndexScanDirectedRelationshipIndexSeekUndirectedRelationshipIndexSeek

USING [RANGE | TEXT | POINT] INDEX SEEK variable:RELATIONSHIP_TYPE(property)

DirectedRelationshipIndexSeekUndirectedRelationshipIndexSeek

在为提示指定索引类型(例如RANGETEXTPOINT)时,仅当存在指定类型的索引时才能满足该提示。当未指定索引类型时,任何索引类型都可以满足该提示。

使用提示绝不能更改查询的结果。因此,仅当计划程序知道使用指定类型的索引不会更改结果时,才能满足具有指定索引类型的提示。有关更多详细信息,请参阅索引的使用

可以提供多个索引提示,但请记住,多个起点需要在查询计划的后面使用潜在的昂贵连接。

使用节点索引提示的查询

上面的查询可以进行调整以选择不同的索引作为起点。

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING INDEX p:Pioneer(born)
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator        | Details                                             | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults | c, cc, i, p, s, sc                                  |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | cc.formed = $autoint_3 AND cc:Country               |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (c)-[anon_2:PART_OF]->(cc)                          |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | c:City                                              |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (p)-[anon_1:LIVES_IN]->(c)                          |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | s.born = $autoint_0 AND s:Scientist                 |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (sc)<-[anon_0:RESEARCHED]-(s)                       |              0 |    0 |       0 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter         | i.year = $autoint_1 AND sc:Science                  |              0 |    0 |       2 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)    | (p)-[i:INVENTED_BY]->(sc)                           |              2 |    2 |       6 |                |                        |           |                     |
| |               +-----------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek  | RANGE INDEX p:Pioneer(born) WHERE born = $autoint_2 |              2 |    2 |       3 |            120 |                    4/1 |     0.491 | Fused in Pipeline 0 |
+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 11, total allocated memory: 208

使用节点文本索引提示的查询

以下查询可以进行调整以选择文本索引。

查询
PROFILE
MATCH (c:Country)
USING TEXT INDEX c:Country(name)
WHERE c.name = 'Country7'
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator        | Details                                               | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults | c                                                     |              1 |    1 |       0 |                |                        |           |                     |
| |               +-------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek  | TEXT INDEX c:Country(name) WHERE name = $autostring_0 |              1 |    1 |       2 |            120 |                    2/0 |     0.949 | Fused in Pipeline 0 |
+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 2, total allocated memory: 184

使用关系索引提示的查询

上面的查询可以进行调整以选择关系索引作为起点。

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING INDEX i:INVENTED_BY(year)
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+--------------------------------+---------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator                       | Details                                                             | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+--------------------------------+---------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults                | c, cc, i, p, s, sc                                                  |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                        | cc.formed = $autoint_3 AND cc:Country                               |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                   | (c)-[anon_2:PART_OF]->(cc)                                          |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                        | c:City                                                              |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                   | (p)-[anon_1:LIVES_IN]->(c)                                          |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                        | s.born = $autoint_0 AND s:Scientist                                 |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                   | (sc)<-[anon_0:RESEARCHED]-(s)                                       |              0 |    0 |       0 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                        | p.born = $autoint_2 AND sc:Science AND p:Pioneer                    |              0 |    0 |       4 |                |                        |           |                     |
| |                              +---------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +DirectedRelationshipIndexSeek | RANGE INDEX (p)-[i:INVENTED_BY(year)]->(sc) WHERE year = $autoint_1 |              2 |    2 |       3 |            120 |                    5/1 |     0.461 | Fused in Pipeline 0 |
+--------------------------------+---------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 7, total allocated memory: 208

使用关系文本索引提示的查询

以下查询可以进行调整以选择文本索引。

查询
PROFILE
MATCH ()-[i:INVENTED_BY]->()
USING TEXT INDEX i:INVENTED_BY(location)
WHERE i.location = 'Location7'
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+--------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator                       | Details                                                                                | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+--------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults                | i                                                                                      |              1 |    1 |       0 |                |                        |           |                     |
| |                              +----------------------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +DirectedRelationshipIndexSeek | TEXT INDEX (anon_0)-[i:INVENTED_BY(location)]->(anon_1) WHERE location = $autostring_0 |              1 |    1 |       2 |            120 |                    3/0 |     1.079 | Fused in Pipeline 0 |
+--------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 2, total allocated memory: 184

使用多个索引提示的查询

提供一个索引提示更改了查询的起点,但计划仍然是线性的,这意味着它只有一个起点。如果我们再给计划程序另一个索引提示,我们强制它使用两个起点,一个在匹配的每一端。然后,它将使用连接运算符连接这两个分支。

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING INDEX s:Scientist(born)
USING INDEX cc:Country(formed)
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator         | Details                                                  | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults  | c, cc, i, p, s, sc                                       |              0 |    0 |       0 |                |                    0/0 |     0.000 |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+                     |
| +NodeHashJoin    | sc                                                       |              0 |    0 |       0 |            432 |                        |           | In Pipeline 2       |
| |\               +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| | +Expand(All)   | (s)-[anon_0:RESEARCHED]->(sc)                            |              1 |    0 |       0 |                |                        |           |                     |
| | |              +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +NodeIndexSeek | RANGE INDEX s:Scientist(born) WHERE born = $autoint_0    |              1 |    0 |       0 |            120 |                    0/0 |     0.000 | Fused in Pipeline 1 |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +Filter          | i.year = $autoint_1 AND sc:Science                       |              0 |    0 |       0 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (p)-[i:INVENTED_BY]->(sc)                                |              0 |    0 |       0 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | p.born = $autoint_2 AND p:Pioneer                        |              0 |    0 |       2 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (c)<-[anon_1:LIVES_IN]-(p)                               |              1 |    1 |       3 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | c:City                                                   |              1 |    1 |       2 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (cc)<-[anon_2:PART_OF]-(c)                               |              1 |    1 |       2 |                |                        |           |                     |
| |                +----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek   | RANGE INDEX cc:Country(formed) WHERE formed = $autoint_3 |              1 |    1 |       2 |            120 |                    7/0 |     0.494 | Fused in Pipeline 0 |
+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 11, total allocated memory: 768

使用多个索引提示进行查询

如果查询在WHERE子句中包含析取(OR),则提供多个索引提示也很有用。这可以确保使用所有提示的索引,并将结果使用UnionDistinct组合在一起。

查询
PROFILE
MATCH (country:Country)
USING INDEX country:Country(name)
USING INDEX country:Country(formed)
WHERE country.formed = 500 OR country.name STARTS WITH "A"
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+-----------------------+------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator              | Details                                                                | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+-----------------------+------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults       | country                                                                |              1 |    1 |       0 |                |                        |           |                     |
| |                     +------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Distinct             | country                                                                |              1 |    1 |       0 |            224 |                        |           |                     |
| |                     +------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Union                |                                                                        |              2 |    1 |       0 |             80 |                    1/0 |     0.213 | Fused in Pipeline 2 |
| |\                    +------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| | +NodeIndexSeek      | RANGE INDEX country:Country(formed) WHERE formed = $autoint_0          |              1 |    1 |       2 |            120 |                    1/0 |     0.101 | In Pipeline 1       |
| |                     +------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +NodeIndexSeekByRange | RANGE INDEX country:Country(name) WHERE name STARTS WITH $autostring_1 |              1 |    0 |       1 |            120 |                    0/1 |     0.307 | In Pipeline 0       |
+-----------------------+------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 3, total allocated memory: 320

Cypher®通常会提供一个使用所有索引进行析取的计划,无需提示。但是,如果谓词似乎选择性不高,它可能会决定改为计划一个NodeByLabelScan。在这种情况下,索引提示可能会有用。

扫描提示

如果您的查询匹配索引的大部分内容,扫描标签或关系类型并过滤掉不匹配的行可能会更快。为此,您可以在适用的MATCH子句之后使用USING SCAN variable:Label(用于节点索引)和USING SCAN variable:RELATIONSHIP_TYPE(用于关系索引)。这将强制Cypher不使用可能已使用的索引,而是执行标签扫描/关系类型扫描。您可以使用相同的提示来强制执行没有索引适用的起始点。

提示标签扫描

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING SCAN s:Scientist
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+------------------+-----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator         | Details                                                   | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+------------------+-----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults  | c, cc, i, p, s, sc                                        |              0 |    0 |       0 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | cc.formed = $autoint_3 AND cc:Country                     |              0 |    0 |       0 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (c)-[anon_2:PART_OF]->(cc)                                |              0 |    0 |       0 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | c:City                                                    |              0 |    0 |       0 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (p)-[anon_1:LIVES_IN]->(c)                                |              0 |    0 |       0 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | i.year = $autoint_1 AND p.born = $autoint_2 AND p:Pioneer |              0 |    0 |       1 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (sc)<-[i:INVENTED_BY]-(p)                                 |              1 |    1 |       3 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | sc:Science                                                |              1 |    1 |       2 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (s)-[anon_0:RESEARCHED]->(sc)                             |              1 |    1 |       2 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | s.born = $autoint_0                                       |              1 |    1 |     200 |                |                        |           |                     |
| |                +-----------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeByLabelScan | s:Scientist                                               |            100 |  100 |     101 |            120 |                   11/0 |     0.512 | Fused in Pipeline 0 |
+------------------+-----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 309, total allocated memory: 216

提示关系类型扫描

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING SCAN i:INVENTED_BY
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+-------------------------------+--------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator                      | Details                                                                  | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+-------------------------------+--------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults               | c, cc, i, p, s, sc                                                       |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                       | cc.formed = $autoint_3 AND cc:Country                                    |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                  | (c)-[anon_2:PART_OF]->(cc)                                               |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                       | c:City                                                                   |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                  | (p)-[anon_1:LIVES_IN]->(c)                                               |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                       | s.born = $autoint_0 AND s:Scientist                                      |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)                  | (sc)<-[anon_0:RESEARCHED]-(s)                                            |              0 |    0 |       0 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter                       | i.year = $autoint_1 AND p.born = $autoint_2 AND sc:Science AND p:Pioneer |              0 |    0 |     204 |                |                        |           |                     |
| |                             +--------------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +DirectedRelationshipTypeScan | (p)-[i:INVENTED_BY]->(sc)                                                |            100 |  100 |     101 |            120 |                    9/0 |     0.910 | Fused in Pipeline 0 |
+-------------------------------+--------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 305, total allocated memory: 208

使用多个扫描提示进行查询

如果查询在WHERE子句中包含析取(OR),则提供多个扫描提示也很有用。这可以确保所有涉及的标签谓词都由UnionNodeByLabelsScan解决。

查询
PROFILE
MATCH (person)
USING SCAN person:Pioneer
USING SCAN person:Scientist
WHERE person:Pioneer OR person:Scientist
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+------------------------+--------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator               | Details                  | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+------------------------+--------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults        | person                   |            180 |  200 |       0 |                |                        |           |                     |
| |                      +--------------------------+----------------+------+---------+----------------+                        |           |                     |
| +UnionNodeByLabelsScan | person:Pioneer|Scientist |            180 |  200 |     202 |            120 |                    6/0 |     1.740 | Fused in Pipeline 0 |
+------------------------+--------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 202, total allocated memory: 184

Cypher通常会提供一个使用扫描进行析取的计划,无需提示。但是,如果标签谓词似乎选择性不高,它可能会决定改为计划一个AllNodeScan,后面跟着一个Filter。在这种情况下,扫描提示可能会有用。

连接提示

连接提示是最高级别的提示类型,不用于查找查询执行计划的起始点,而是用于强制在指定点进行连接。这意味着计划中必须存在多个起始点(叶子),以便查询能够连接从这些叶子向上延伸的两个分支。由于这种性质,连接以及随后的连接提示将强制规划器寻找其他起始点,并且在没有更多好的起始点的情况下,可能会选择一个非常糟糕的起始点。这将对查询性能产生负面影响。在其他情况下,提示可能会强制规划器选择一个看起来很糟糕的起始点,而实际上它被证明是一个非常好的起始点。

提示单个节点上的连接

在上面使用多个索引提示的示例中,我们看到规划器选择进行连接,但不是在p节点上。通过除了索引提示之外还提供连接提示,我们可以强制连接在p节点上发生。

查询
PROFILE
MATCH
  (s:Scientist {born: 1850})-[:RESEARCHED]->
  (sc:Science)<-[i:INVENTED_BY {year: 560}]-
  (p:Pioneer {born: 525})-[:LIVES_IN]->
  (c:City)-[:PART_OF]->
  (cc:Country {formed: 411})
USING INDEX s:Scientist(born)
USING INDEX cc:Country(formed)
USING JOIN ON p
RETURN *
查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+------------------+------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator         | Details                                                          | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+------------------+------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults  | c, cc, i, p, s, sc                                               |              0 |    0 |       0 |                |                    0/0 |     0.000 |                     |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+                     |
| +NodeHashJoin    | p                                                                |              0 |    0 |       0 |            432 |                        |           | In Pipeline 2       |
| |\               +------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| | +Filter        | cache[p.born] = $autoint_2                                       |              1 |    0 |       0 |                |                        |           |                     |
| | |              +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +Expand(All)   | (c)<-[anon_1:LIVES_IN]-(p)                                       |              1 |    0 |       0 |                |                        |           |                     |
| | |              +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +Filter        | c:City                                                           |              1 |    0 |       0 |                |                        |           |                     |
| | |              +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +Expand(All)   | (cc)<-[anon_2:PART_OF]-(c)                                       |              1 |    0 |       0 |                |                        |           |                     |
| | |              +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +NodeIndexSeek | RANGE INDEX cc:Country(formed) WHERE formed = $autoint_3         |              1 |    0 |       0 |            120 |                    0/0 |     0.000 | Fused in Pipeline 1 |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +Filter          | i.year = $autoint_1 AND cache[p.born] = $autoint_2 AND p:Pioneer |              0 |    0 |       1 |                |                        |           |                     |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (sc)<-[i:INVENTED_BY]-(p)                                        |              1 |    1 |       3 |                |                        |           |                     |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Filter          | sc:Science                                                       |              1 |    1 |       2 |                |                        |           |                     |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +Expand(All)     | (s)-[anon_0:RESEARCHED]->(sc)                                    |              1 |    1 |       2 |                |                        |           |                     |
| |                +------------------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek   | RANGE INDEX s:Scientist(born) WHERE born = $autoint_0            |              1 |    1 |       2 |            120 |                    6/1 |     0.515 | Fused in Pipeline 0 |
+------------------+------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 10, total allocated memory: 768

提示可选匹配的连接

连接提示也可用于强制规划器选择NodeLeftOuterHashJoinNodeRightOuterHashJoin来解决OPTIONAL MATCH。在大多数情况下,规划器更倾向于使用OptionalExpand

查询
PROFILE
MATCH (s:Scientist {born: 1850})
OPTIONAL MATCH (s)-[:RESEARCHED]->(sc:Science)
RETURN *

没有任何提示的情况下,规划器没有使用连接来解决OPTIONAL MATCH

查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+----------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator             | Details                                               | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+----------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults      | s, sc                                                 |              1 |    1 |       0 |                |                        |           |                     |
| |                    +-------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +OptionalExpand(All) | (s)-[anon_0:RESEARCHED]->(sc) WHERE sc:Science        |              1 |    1 |       4 |                |                        |           |                     |
| |                    +-------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| +NodeIndexSeek       | RANGE INDEX s:Scientist(born) WHERE born = $autoint_0 |              1 |    1 |       2 |            120 |                    6/0 |     0.560 | Fused in Pipeline 0 |
+----------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 6, total allocated memory: 184
查询
PROFILE
MATCH (s:Scientist {born: 1850})
OPTIONAL MATCH (s)-[:RESEARCHED]->(sc:Science)
USING JOIN ON s
RETURN *

现在规划器使用连接来解决OPTIONAL MATCH

查询计划
Planner COST

Runtime PIPELINED

Runtime version 5.25

Batch size 128

+------------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator               | Details                                               | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline            |
+------------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults        | s, sc                                                 |              1 |    1 |       0 |                |                    2/0 |     0.213 |                     |
| |                      +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+                     |
| +NodeLeftOuterHashJoin | s                                                     |              1 |    1 |       0 |           3112 |                        |     0.650 | In Pipeline 2       |
| |\                     +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| | +Expand(All)         | (sc)<-[anon_0:RESEARCHED]-(s)                         |            100 |  100 |     300 |                |                        |           |                     |
| | |                    +-------------------------------------------------------+----------------+------+---------+----------------+                        |           |                     |
| | +NodeByLabelScan     | sc:Science                                            |            100 |  100 |     101 |            120 |                    4/0 |     0.786 | Fused in Pipeline 1 |
| |                      +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +NodeIndexSeek         | RANGE INDEX s:Scientist(born) WHERE born = $autoint_0 |              1 |    1 |       2 |            120 |                    1/0 |     0.214 | In Pipeline 0       |
+------------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+

Total database accesses: 403, total allocated memory: 3192