neo4j:根据返回限制更改执行计划

问题描述 投票:0回答:1

在我们的neo4j 5.5版数据库中,我们有数据

(c1:Company)-[:ADDRESS_MATCH]-(c2:company)
以及
(t:CompanyNameToken)-[:CONTAINS_TOKEN]-(c:Company)
。我们的目标是找到具有地址匹配和通用令牌的公司。执行计划意外改变,如下。仅匹配地址是快速的,并产生以下执行计划,在 14 毫秒内命中 1645 个数据库。

PROFILE MATCH (c1:Company)-[:ADDRESS_MATCH]->(c2:Company)
RETURN c1, c2 LIMIT 100

增加 100 的限制或取消限制时,执行计划保持不变。现在添加令牌匹配作为条件,对于

LIMIT 100
,执行计划仍然只有一个分支,在 58 毫秒内有 250.000 次 DB 命中。

PROFILE MATCH (c1:Company)-[:ADDRESS_MATCH]->(c2:Company),
(c1)<-[r1:CONTAINS_TOKEN]-(t:CompanyNameToken)-[r2:CONTAINS_TOKEN]->(c2)
RETURN c1, c2 LIMIT 100

但是,当使用

LIMIT 300
而不是
LIMIT 100
执行相同的查询时,执行计划涉及多个分支(
c1
c2
上的笛卡尔积)并且在更长的 12000 毫秒内突然有 3800 万次 DB 命中。 (过渡介于 200 和 300 之间)。

PROFILE MATCH (c1:Company)-[:ADDRESS_MATCH]->(c2:Company),
(c1)<-[r1:CONTAINS_TOKEN]-(t:CompanyNameToken)-[r2:CONTAINS_TOKEN]->(c2)
return c1, c2 limit 300

使用

exists
关键字重新表述上述查询不会显示此行为。执行计划保持不变,独立于限制,甚至没有限制。对于
LIMIT 300
,它仅在 190 毫秒内就有 600.000 次 DB 命中。

PROFILE MATCH (c1:Company)-[:ADDRESS_MATCH]->(c2:Company)
WHERE EXISTS {(c1)<-[r1:CONTAINS_TOKEN]-(t:CompanyNameToken)-[r2:CONTAINS_TOKEN]->(c2)}
return c1, c2 limit 300

三个问题:

  • 这种行为的原因是什么?
  • LIMIT 100
    的执行计划是应该的,避免了不必要的笛卡尔积。
    LIMIT 300
    的计划天真得无可救药。有没有办法强制 neo4j 执行第一个执行计划,也许有一些计划提示?
  • 为什么使用涉及
    EXISTS
    的变体时执行计划不同?

我尝试了各种规划器提示和组合,但都没有成功。令人困惑的是,几天前,这种行为并没有出现,数据几乎相同。我读到执行计划取决于数据库统计信息。但是,像

CALL db.clearQueryCaches()
CALL db.prepareForReplanning()
这样的命令也没有改变行为。

neo4j query-optimization database-performance sql-execution-plan
1个回答
0
投票

关于EXISTS函数,一旦找到一个匹配项,它会立即返回

true
。因此,与查找并保存所有匹配项相比,它可以更快,占用内存更少

由于您的用例不需要使用 all

CompanyNameToken
子路径,因此只使用
EXISTS
版本的查询是有意义的。

© www.soinside.com 2019 - 2024. All rights reserved.