标签顺序会影响搜索时间吗?
Do labels order effects search time?
我正在使用 neo4j 2.1.7 最近我正在试验匹配查询,搜索具有多个标签的节点。我发现,通常查询
Match (p:A:B) return count(p) as number
和
Match (p:B:A) return count(p) as number
工作时间不同,尤其是在您有 200 万个节点 A 和 0 个节点 B 的情况下。
那么标签顺序会影响搜索时间吗?这个未来在任何地方都有记录吗?
Neo4j 在内部维护一个 labelscan 存储 - 这基本上是一个查找,可以快速获取所有带有定义标签的节点 A
。
在执行类似
的查询时
MATCH (n:A:B) return count(n)
labelscanstore 用于查找所有 A
节点,然后如果这些节点也带有标签 B
,则对它们进行过滤。如果 n(A) >> n(B)
执行 MATCH (n:B:A)
效率更高,因为您只查找几个 B
节点并为 A.
过滤这些节点
您可以使用PROFILE MATCH (n:A:B) return count(n)
查看查询计划。对于 Neo4j <= 2。1.x 根据您指定的标签顺序,您将看到不同的查询计划。
从 Neo4j 2.2 开始(在撰写此回复时里程碑 M03 可用)有一个基于成本的 Cypher 优化器。现在 Cypher 知道节点统计信息并用于优化查询。
例如,我使用以下语句创建了一些测试数据:
create (:A:B);
with 1 as a foreach (x in range(0,1000000) | create (:A));
with 1 as a foreach (x in range(0,100) | create (:B));
我们现在有100个B节点,1M个A节点和1个AB节点。 2.2中的两条语句:
MATCH (n:B:A) return count(n)
MATCH (n:A:B) return count(n)
产生完全相同的查询计划(因此具有相同的执行速度):
+------------------+---------------+------+--------+-------------+---------------+
| Operator | EstimatedRows | Rows | DbHits | Identifiers | Other |
+------------------+---------------+------+--------+-------------+---------------+
| EagerAggregation | 3 | 1 | 0 | count(n) | |
| Filter | 12 | 1 | 12 | n | hasLabel(n:A) |
| NodeByLabelScan | 12 | 12 | 13 | n | :B |
+------------------+---------------+------+--------+-------------+---------------+
由于只有少数 B
个节点,扫描 B 并过滤 A
的成本更低。智能密码,不是吗 ;-)
我正在使用 neo4j 2.1.7 最近我正在试验匹配查询,搜索具有多个标签的节点。我发现,通常查询
Match (p:A:B) return count(p) as number
和
Match (p:B:A) return count(p) as number
工作时间不同,尤其是在您有 200 万个节点 A 和 0 个节点 B 的情况下。 那么标签顺序会影响搜索时间吗?这个未来在任何地方都有记录吗?
Neo4j 在内部维护一个 labelscan 存储 - 这基本上是一个查找,可以快速获取所有带有定义标签的节点 A
。
在执行类似
的查询时MATCH (n:A:B) return count(n)
labelscanstore 用于查找所有 A
节点,然后如果这些节点也带有标签 B
,则对它们进行过滤。如果 n(A) >> n(B)
执行 MATCH (n:B:A)
效率更高,因为您只查找几个 B
节点并为 A.
您可以使用PROFILE MATCH (n:A:B) return count(n)
查看查询计划。对于 Neo4j <= 2。1.x 根据您指定的标签顺序,您将看到不同的查询计划。
从 Neo4j 2.2 开始(在撰写此回复时里程碑 M03 可用)有一个基于成本的 Cypher 优化器。现在 Cypher 知道节点统计信息并用于优化查询。
例如,我使用以下语句创建了一些测试数据:
create (:A:B);
with 1 as a foreach (x in range(0,1000000) | create (:A));
with 1 as a foreach (x in range(0,100) | create (:B));
我们现在有100个B节点,1M个A节点和1个AB节点。 2.2中的两条语句:
MATCH (n:B:A) return count(n)
MATCH (n:A:B) return count(n)
产生完全相同的查询计划(因此具有相同的执行速度):
+------------------+---------------+------+--------+-------------+---------------+
| Operator | EstimatedRows | Rows | DbHits | Identifiers | Other |
+------------------+---------------+------+--------+-------------+---------------+
| EagerAggregation | 3 | 1 | 0 | count(n) | |
| Filter | 12 | 1 | 12 | n | hasLabel(n:A) |
| NodeByLabelScan | 12 | 12 | 13 | n | :B |
+------------------+---------------+------+--------+-------------+---------------+
由于只有少数 B
个节点,扫描 B 并过滤 A
的成本更低。智能密码,不是吗 ;-)