Neo4j查询不使用索引

nom7f22z  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(129)

我有几种节点标签(Asset 1,Asset 2等),所有这些都可以连接到任何其他资产;每个资产都有不同的字段,但都有一个共同的id字段。我将这些数据保存在CSV文件中以加载到Neo4j中:节点数据保存在asset1.csv,asset2.csv等中,而关系数据保存在具有以下标题的连接.csv文件中:asset_1_idasset_1_typeasset_2_idasset_2_type
加载节点很容易:

LOAD CSV WITH HEADERS FROM 'file:///assetN.csv' AS row
CREATE (n:AssetN {
  id: row.id,
  // other fields for AssetN
})

字符串
在加载节点之前,我为每个资产类型定义了单独的索引:

CREATE INDEX assetN_id IF NOT EXISTS FOR (n:AssetN) ON (n.id);


加载关系有点棘手,因为我的第一个解决方案永远不会终止:

LOAD CSV WITH HEADERS FROM 'file:///connection.csv' AS row
MATCH (asset1 { id: row.asset_1_id })
MATCH (asset2 { id: row.asset_2_id }) 
    
MERGE (asset1)-[:CONNECTED_TO]-(asset2)


似乎如果我不指定标签类型,Neo4j不会在存在的情况下查找索引。我理解有时它可能不存在(例如,假设有另一种资产类型没有定义该索引),但我希望它尝试,然后默认为全扫描。
所以我的第二个解决方案是尝试使用APOC从CSV文件中动态读取标签:

LOAD CSV WITH HEADERS FROM 'file:///connection.csv' AS row
CALL apoc.merge.node([row.asset_1_type], { mrid: row.asset_1_id }) YIELD node as asset1
CALL apoc.merge.node([row.asset_2_type], { mrid: row.asset_2_id }) YIELD node as asset2   
 
MERGE (asset1)-[:CONNECTED_TO]-(asset2)


但这也永远不会终止,因为它似乎仍然没有使用索引。
到目前为止,我发现的唯一有效的解决方案是为每个资产类型定义一个额外的标签(称为Asset),在Asset上定义一个索引,然后加载关系数据:

LOAD CSV WITH HEADERS FROM 'file:///connection.csv' AS row
MATCH (asset1:Asset { id: row.asset_1_id })
MATCH (asset2:Asset { id: row.asset_2_id }) 
    
MERGE (asset1)-[:CONNECTED_TO]-(asset2)


这是非常快的,因为它实际上使用了索引,但我不喜欢仅仅为了优化数据加载而必须向每个节点添加标签。
还有其他我没有看到的解决方案吗?

watbbzwu

watbbzwu1#

Neo4j不要求节点有一致的标签,所以每个节点可以有任意数量的标签(包括0)。
现在,让我们假设Cypher执行规划器是“超级智能”的,如果你没有指定任何标签,* 可以 * 自动使用索引。在这种情况下,规划器必须测试 * 每个匹配节点 * 的标签,然后尝试确定一个单一的连贯计划,使用涉及这些标签的索引组合,以最大限度地减少执行时间。
由于这需要扫描所有匹配的节点来提出执行计划,因此我们已经淹没了通过执行带有索引的结果计划所获得的任何加速。
所以,一个“超级智能”的Cypher计划器太慢了,没有任何用处。

dxpyg8gm

dxpyg8gm2#

AFAIK,Cypher不支持动态标签。但apoc库支持:请参阅
https://neo4j.com/labs/apoc/4.1/overview/apoc.merge/apoc.merge.node/

相关问题